From 595d9e6ebbb97757cecf0ade7228b8f8f7420eeb Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Mon, 10 Jul 2023 21:50:03 +0900 Subject: fix: don't use control flow when extracted fn contains tail expr of original fn --- .../ide-assists/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 e9db38aca0f..80a60b4a667 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 } -- cgit 1.4.1-3-g733a5 From 008b639ef525533dc03ff6c73f05de13ab6f202d Mon Sep 17 00:00:00 2001 From: Max Heller Date: Thu, 27 Jul 2023 21:17:10 -0400 Subject: 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 d7d44e41388..6fe429c8d9a 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 6f80bb6e07c..96c176d60f4 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 46633667ed3..7dffd6fc18a 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) } -- cgit 1.4.1-3-g733a5 From 37a8493138c43caebfe7b62964a2558d21d1be25 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Fri, 28 Jul 2023 06:45:35 -0400 Subject: 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 ddf668d20b0..703eac7063f 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 5ded4b6b273..4180f817209 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 00e21433daa..2e18e7c6d19 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 + ``` + "#]], + ); +} -- cgit 1.4.1-3-g733a5 From f42d361a22fadd7ddff4d4474b0c896387c7557c Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Sat, 29 Jul 2023 06:58:29 +0000 Subject: 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 6cce3a56f08..c427772c082 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 0411890ab51..3b11bfc02ab 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 0aa3d6265dc..81a6914815e 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 4d7ebe3fefe..127020c03ba 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 00000000000..4f8cab3bf0e --- /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 02c5dd5bfb7..a68d4945d82 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 48a6af3dd4c..68cfce4065c 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 -- cgit 1.4.1-3-g733a5 From 784379eb796deb3c799473093f59555eb8cf17f1 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 29 Jul 2023 15:23:35 -0400 Subject: 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 3ea50659030..4f5266051be 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 8cb1ff4a125..4869ac17ad9 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:: + "#]], + ); +} -- cgit 1.4.1-3-g733a5 From c4cff802691aa1ffb3da820e89dfecc41ef13de7 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 30 Jul 2023 11:12:49 -0400 Subject: 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 4f5266051be..aeec1ea6f77 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| { -- cgit 1.4.1-3-g733a5 From b9ee4a51678ad4ed1bd93b9fc756b3d2877959d3 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 30 Jul 2023 15:36:42 -0400 Subject: 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 e4705475638..de855242ee3 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 3cb65b2729a..8ec5c6c8bfd 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 aeec1ea6f77..cc9e4581bed 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 4869ac17ad9..2a05aef17f9 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:: "#]], -- cgit 1.4.1-3-g733a5 From 3205ed7a41ef016d0b445cf723c3eb5684956270 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Wed, 2 Aug 2023 09:19:56 -0400 Subject: simplify storing generic parameter attributes in item tree --- crates/hir-def/src/generics.rs | 27 ++++++++++++++------ crates/hir-def/src/item_tree/lower.rs | 47 ++++++++++------------------------- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 6fe429c8d9a..b0fb27e81d9 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 7dffd6fc18a..d66ea743e86 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); - - 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()), - ); - } + 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); } - } - 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()), - ); + Entry::Vacant(entry) => { + entry.insert(attrs); } } - } + }; + generics.fill(&self.body_ctx, node, add_param_attrs); + generics.shrink_to_fit(); Interned::new(generics) } -- cgit 1.4.1-3-g733a5 From f4038a6bf1927aee3c5a34d7ffe14da4e7ba0560 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 1 Aug 2023 18:15:32 -0400 Subject: support AssocTypeArg and MethodCalls --- crates/ide-completion/src/context/analysis.rs | 94 +++++++++++++++++-------- crates/ide-completion/src/tests/type_pos.rs | 98 +++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 34 deletions(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index cc9e4581bed..7fd3147a739 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 2a05aef17f9..67110b3d7fb 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; + 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; 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; -fn foo() {} +struct Foo; +impl Foo { fn bar(self) {} } fn main() { - foo::(); + 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:: + "#]], + ); } -- cgit 1.4.1-3-g733a5 From 1b3e20fe686e5544feb134a7b1ffcd406a1189e6 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Wed, 2 Aug 2023 17:59:26 -0400 Subject: 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 | 180 ++++++++++++++------------ 3 files changed, 128 insertions(+), 98 deletions(-) diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index de855242ee3..69b1e1fd11f 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 7fd3147a739..4bd429c5723 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 67110b3d7fb..27bcf4c630a 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,51 +760,18 @@ 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>(); +trait Bar { + type Baz; } -"#, +fn foo(_: impl Bar = ()>) {} + "#, expect![[r#" en Enum ma makro!(…) macro_rules! makro @@ -798,6 +780,7 @@ fn main() { st Record st Tuple st Unit + tt Bar tt Trait un Union bt u32 @@ -806,47 +789,84 @@ fn main() { "#]], ); - check( + 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; -trait Bar { - type Baz; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::(); } -fn foo = ()>>() {} -"#, - expect![[r#" - ct CONST - ct X - ma makro!(…) macro_rules! makro - kw crate:: - kw self:: - "#]], - ); - check( + "#, + // Associated type params 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:: - "#]], - ); +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:: + "#]], + ); + } } -- cgit 1.4.1-3-g733a5 From 50db877bfa8a03dfaddb80f03737d62bce38f9a5 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:00:39 -0400 Subject: 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 b0fb27e81d9..540fa115a00 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); -- cgit 1.4.1-3-g733a5 From ee39905370c84085335276b49c04d58399cb3697 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:10:00 -0400 Subject: 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 27bcf4c630a..6369f31788c 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#" -- cgit 1.4.1-3-g733a5 From 5e6d646ccc0677f6ea68da7ef964cfee2c1e28f0 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:14:44 -0400 Subject: 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 4bd429c5723..8de4d0827f9 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) => { -- cgit 1.4.1-3-g733a5 From d48606fefed56931414313d4f10ac8b53756c5df Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 08:22:58 -0400 Subject: unroll test loop --- crates/ide-completion/src/tests/type_pos.rs | 191 +++++++++++++++++++--------- 1 file changed, 131 insertions(+), 60 deletions(-) diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 6369f31788c..31ff9cf956e 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,45 +725,48 @@ 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#" -const X: usize = 0; struct Foo; -impl Foo { fn bar(self) {} } +const X: usize = 0; +fn foo() {} fn main() { - Foo.bar::<_, $0>(); + foo::<_, $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#" + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], + ); + // Method generic params check( r#" const X: usize = 0; struct Foo; -trait Bar { - type Baz; +impl Foo { fn bar(self) {} } +fn main() { + Foo.bar::<_, $0>(); } -fn foo(_: impl Bar = ()>) {} "#, expect![[r#" en Enum @@ -773,7 +776,6 @@ fn foo(_: impl Bar = ()>) {} st Record st Tuple st Unit - tt Bar tt Trait un Union bt u32 @@ -781,27 +783,51 @@ fn foo(_: impl Bar = ()>) {} kw self:: "#]], ); - - let const_completion_cases = [ - // Function params + check( r#" -struct Foo; const X: usize = 0; -fn foo() {} +struct Foo; +impl Foo { fn bar(self) {} } fn main() { - foo::<_, $0>(); + Foo.bar::(); } "#, - // Method params + 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; struct Foo; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::(); +trait Bar { + type Baz; } +fn foo(_: impl Bar = ()>) {} "#, - // Associated type params + 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:: + "#]], + ); + 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:: + "#]], + ); } -- cgit 1.4.1-3-g733a5 From bed1114b8ba258acb243c938e7b2915424426474 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sat, 5 Aug 2023 09:07:29 -0400 Subject: 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 | 341 ++++++++++++++------------ 3 files changed, 221 insertions(+), 155 deletions(-) diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 69b1e1fd11f..f4efaecba8a 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 8de4d0827f9..dfceb67f209 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 31ff9cf956e..4b441391094 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:: + "#]], + ); + check( + r#" + struct Foo; + const X: usize = 0; + fn foo() {} + fn main() { + foo::<_, $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:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); + + // Method generic params check( r#" -struct Foo; -const X: usize = 0; -fn foo() {} -fn main() { - foo::<_, $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:: + "#]], + ); + 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:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); - // Method generic params + // Associated type 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; + 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:: + "#]], + ); + 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 Trait - un Union - bt u32 - 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; -impl Foo { fn bar(self) {} } -fn main() { - Foo.bar::(); -} - "#, + 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:: + "#]], ); - // Associated type generic params + // Type alias generic params check( r#" -const X: usize = 0; -struct Foo; -trait Bar { - type Baz; -} -fn foo(_: impl Bar = ()>) {} - "#, + const X: usize = 0; + struct Foo(T); + type Bar = Foo; + fn main() { + let _: Bar:: = 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:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); + + // Enum variant params check( r#" -const X: usize = 0; -struct Foo; -trait Bar { - type Baz; -} -fn foo = ()>>() {} - "#, + 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:: + "#]], ); - // Type generic params + // Trait params check( r#" -const X: usize = 0; -struct Foo(T); -fn main() { - let _: Foo::<_, $0> = Foo(()); -} - "#, + 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:: + "#]], ); - // Type alias generic params + // Trait alias params check( r#" -const X: usize = 0; -struct Foo(T); -type Bar = Foo; -fn main() { - let _: Bar:: = Bar(()); -} - "#, + #![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:: - "#]], + ct CONST + ct X + ma makro!(…) macro_rules! makro + kw crate:: + kw self:: + "#]], ); - // Enum variant params + // Omitted lifetime params check( r#" -const X: usize = 0; -enum Foo { A(T), B } -fn main() { - Foo::B::<(), $0>; -} +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:: "#]], ); - - // Trait params + // Explicit lifetime params check( r#" -const X: usize = 0; -trait Foo {} -impl Foo<(), $0> for () {} +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 - 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>() {} +struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); +fn foo<'a>() { S::<'static, F$0, _, _>; } "#, expect![[r#" - ct CONST - ct X + lt 'a ma makro!(…) macro_rules! makro kw crate:: kw self:: -- cgit 1.4.1-3-g733a5 From 9b636e23265705f5ca4f5965a0e207fefd869990 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 6 Aug 2023 01:46:29 +0330 Subject: 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 323ee4260e4..aaac0fc3790 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 c47799f1320..b75c7079be7 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 b2e29fd34b5..bfd7d7c1f2c 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 46165cf3d69..ff30dc6dade 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( -- cgit 1.4.1-3-g733a5 From 0c433c23b155734aa190157c8899b5d854a75c5a Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Mon, 7 Aug 2023 00:59:35 +0900 Subject: 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 b112c1070d4..d04d2fa0e97 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 0f2fb2c8118..cd0410168c2 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 bf041b61f2f..de60c88844d 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 5e4562d9c58..4ce80532e8e 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 05a64b33bfd..8036c77072b 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( -- cgit 1.4.1-3-g733a5 From bb9d8229b87163d073bc1329bdc4f42676bead07 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Sun, 6 Aug 2023 12:04:29 -0400 Subject: cleanup --- crates/ide-completion/src/completions.rs | 4 +- crates/ide-completion/src/completions/type.rs | 115 ++++++++------------------ 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, 120 insertions(+), 111 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 480cb77b4fd..125ebc98a52 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 f4efaecba8a..621dea0b9a5 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); - - 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 + 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(); + + 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 8ec5c6c8bfd..5537673d1ee 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 dfceb67f209..87380067e87 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 4b441391094..f2ed7247039 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: 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 87380067e87..2064ae34dd9 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() -- cgit 1.4.1-3-g733a5 From b96e4f2f4a209d2dd1fa3c87c26d370258003f1b Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Mon, 7 Aug 2023 02:12:35 +0330 Subject: 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 666955fa1c3..666a7e81e31 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 718df8331e2..9eaa9e1c2f5 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 { -- cgit 1.4.1-3-g733a5 From aa55ce9567af6e810b66744f64981f2eb2ed0082 Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Mon, 7 Aug 2023 12:03:15 +0300 Subject: 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 | 32 +- 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 +- .../src/macro_expansion_tests/builtin_fn_macro.rs | 2 +- crates/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 +- crates/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 ++- crates/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 +-- crates/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 +- crates/ide-assists/src/handlers/add_turbo_fish.rs | 4 +- .../convert_two_arm_bool_match_to_matches_macro.rs | 125 ++-- .../src/handlers/destructure_tuple_binding.rs | 2 +- .../ide-assists/src/handlers/expand_glob_import.rs | 2 +- .../ide-assists/src/handlers/extract_function.rs | 2 +- crates/ide-assists/src/handlers/extract_module.rs | 2 +- .../src/handlers/generate_default_from_new.rs | 38 +- .../src/handlers/generate_delegate_trait.rs | 70 +- .../ide-assists/src/handlers/generate_function.rs | 3 +- crates/ide-assists/src/handlers/inline_call.rs | 2 +- crates/ide-assists/src/handlers/inline_macro.rs | 3 +- .../ide-assists/src/handlers/move_const_to_impl.rs | 16 +- .../src/handlers/remove_unused_imports.rs | 739 +++++++++++++++++++++ .../handlers/replace_derive_with_manual_impl.rs | 14 +- .../handlers/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 ++++-- crates/ide-diagnostics/src/handlers/macro_error.rs | 5 +- .../ide-diagnostics/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 | 88 ++- 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 +- crates/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 +- crates/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 c29446d8235..fae07111806 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 152c02743f7..3853a6ab3a5 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 eeaed87164d..5d71abe37cc 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 69741c445fb..2a90a09f25e 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 bb79e28f267..4cfd318a433 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 54fe9a2e844..91db68058b0 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 82e6dfb30c8..e34a6768f28 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 4197d010608..d0f2bfab432 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 cc85bd893ac..6db8398bc98 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::()?; - - 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)) - }) - }) + 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)) + }) + }), + } } } diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 8a140a1ec18..6591c92ac62 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 2ac1bcdc079..873accafb43 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 6f80bb6e07c..c9b0f75f1a8 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 46633667ed3..7b898e62dba 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 ddf668d20b0..da30830fe45 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 1e74e2dfcb4..1901db8a0f9 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 b232651db96..1250cbb742c 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 b26f9867580..2170cadcf83 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 c048716d740..eef54fc492e 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 e82e97b628e..9cffb3c9f37 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 4931c36bbca..40d3a16540d 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 10f5702845e..b112c1070d4 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 309c0930d1a..5292a5fa1b1 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 876813eab5d..4110f284759 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 54e74d50c87..ade4a592893 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 9ed6c31ddde..1f1e20f49e3 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 98ebe557245..666955fa1c3 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 9253e31d77b..2855f789001 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 5aaa2bcc7c2..a94a962c1f8 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 96787959e1f..1b4ee4613d6 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 0a617dae7d4..b4915dbf0f9 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 00000000000..9e1c74b16fa --- /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 972e5321a47..1781f6c58f1 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 72e6443beb7..8cbdae62526 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 f517bc2c09f..396ca0044ff 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 ffc7a6f2ebd..b15339d4434 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 922e49d281d..4723c25ed08 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 7bd2756c14f..9e30eed56f3 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)); - } - } - 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; + for (id, it) in body.locals.iter() { + if id == return_slot() { + if let Some(destination) = destination { + locals.ptr.insert(id, destination); + continue; } - 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 9ad6087cad9..b2e29fd34b5 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 93f4b699147..46165cf3d69 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 9f25175a3a9..718df8331e2 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 425432479e8..e75b037e38d 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 b71c457f015..1e6e946a13f 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 59046c0435a..5d809b82392 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 8b95110233f..6ea059065e9 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 a0ff628435f..2ad7946c8ac 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 cf8db2a5a24..0f2fb2c8118 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 f3a0608944b..936581bfe32 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 4de9c872ad6..9dfb98e459b 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 de23902199f..fc4bbffdb83 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 b46a3856d45..31cf8ba3364 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 b094bb7a068..bf041b61f2f 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 39a3e1c4489..e99d2984c36 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 b971ca62387..aabda365560 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 d07c6372628..6aca716bb60 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 ac0b74ee8e7..3b162d7c4d8 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 acf82e4b257..36f68d17677 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 b1b0f587cd3..6a5b11f5425 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 ea71d165e6a..f30ca2552d3 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 e9db38aca0f..b8b781ea48d 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 de37f5f130f..6839c5820dc 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 860372941f7..7e4f140a28f 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 185f47184d4..f4fa6a74c6b 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 8085572497a..5b13e01b133 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 67036029f5e..ffab58509b1 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 5aa8e56f562..5d956b1a5e8 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 e1849eb71d5..22d536b5afc 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 00000000000..dd4839351fb --- /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 c03bc2f41d5..ac45581b7b4 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 e7b62d49bb8..c7c0be4c7d4 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 a82f1f9dd8b..2ebb5ef9b19 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 344f2bfcce1..cc3e251a8f2 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 4d47a199b7c..6eadc3dbcbc 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 03d8553506f..a262570d94e 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 e850f7bfdf3..0309952c29a 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 3824720839e..e80a289049f 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 c8341fed1c7..b63dde2c21e 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 52a23b4b8f3..aa0bb7cce69 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 f3c0f79c589..d5abd099126 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 fad0ca51a02..39763479c65 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 937e2f96642..f54cdd63bbb 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 bb0e36ff3a1..acc31cd117a 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 4ac9d0a9fb7..ee0e0354906 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 96c193bd539..ca76d0a87b9 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 c90ba212535..d240127f376 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 e70bc2ec541..c39c696cfd9 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 4e641357e37..21471ab2a03 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 a1a119629a9..37166bdbd0c 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) + 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, + }) + } + 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) } - }) - } - 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) + 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) } - }) - } - 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(); + _ => 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 7e545491f8e..43e89a334bf 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 5ef6ac94807..40659e6c263 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 ef33386a7e9..a33a6ee1816 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 00e21433daa..ddc71dffa8a 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 + Decl docs! - Printed? - abc123 - "#]], + 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 0ad4c6c47e6..bf77d55d58e 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 d486a794e13..17f3771b1a5 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 c7abecb4f1e..d1479dd1e58 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 fdc5261ac38..813f9ed943f 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 e10c4638102..dae8e71e8a0 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 9fa0e6449b8..5f87a78551d 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 deaf3c9c416..d8d81869a2f 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 59e8300dcdb..d8696198d3b 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 3c40246a69d..8e96bfa01ad 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 901df147d32..2657a641482 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 b15f7bca72b..88a008796b3 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 fd3b39855e2..2043752bc74 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 c5fcec75680..06b66b302ae 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 dcac8eb7368..3ac8aa9cc9d 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 696aa590025..8749d355c85 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 8e2181e977e..f2d89d3efe5 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 1a7b7eed295..1471af98b75 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 6161af18587..cdac2f1e3bb 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 665bce474a6..9d886a1c979 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 9b2df89f9c7..73a27df5dbc 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 a868419821d..333318f53b7 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 1c056819f4b..4e850b1f74d 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 1aba1f7674f..c155e8aaf67 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 6e3ae656b02..53cdad64992 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 a8fbcfacf7e..48f407623d8 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 1980d4c78bb..fe18451d384 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 33d7b5ed878..f446a7c0596 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 0db5fb4740e..8541be715a9 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 b63a266a57a..e1704199151 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 4579aca3021..44337f955e5 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 aad74b7466a..5f1f731cffb 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 18d9151d4aa..0a2bb822475 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 7a89533a5e9..7b32180e3eb 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 b096c997448..138ddd20897 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 606804aea25..a150d9e6c07 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 e520801ea2e..0b27faa535d 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 bed240a6d73..4cd668a0cd5 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 c5783b91a0f..e4db33f1c69 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 1b8d4ba42a5..b5a72bec079 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 2cf985adabc..5dafd1a4c8c 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 1c94f13d745..20fe781ae9e 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 a4897899cab..76d7e91f381 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 a047f9659a9..0e64054c11d 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 ac144cbebb2..16c14ca54f2 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 c893d390554..57881803a6a 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 a910e012b73..f0cd3539975 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"] -- cgit 1.4.1-3-g733a5 From 31c30933cf0a94929d533078a402f15a1d350055 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Tue, 8 Aug 2023 01:49:34 +0330 Subject: 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 666a7e81e31..74c62a08a2b 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 bfd7d7c1f2c..52943e97ac0 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, -- cgit 1.4.1-3-g733a5 From 9cb1f45e6f1aedddb475aa61a7bebd9fb26cc094 Mon Sep 17 00:00:00 2001 From: Adam Sandberg Ericsson Date: Sat, 13 May 2023 15:12:32 +0100 Subject: 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 fa20c796ec2..4a31e0ba0a3 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 33422fd058e..b65f38a0c71 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 e1d1130ff1b..06564578d80 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 ea00c9540ff..820535cc1b0 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 cd8b40e3557..f6b8450eef1 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", -- cgit 1.4.1-3-g733a5 From cba39f8553e751e6fb4626653153b1e980472565 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 8 Aug 2023 14:43:26 +0200 Subject: fix: Fix float parser hack creating empty NameRef tokens --- .../src/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 d8e4a4dcc7c..b783de4ccc2 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 62b2accf5cd..7b9bb61e696 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 53cdad64992..2c47e3d086d 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 4cd668a0cd5..27c8a13e58d 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(); -- cgit 1.4.1-3-g733a5 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: 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 49a825e579b..e487b9b4622 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; -- cgit 1.4.1-3-g733a5 From ef5c6daf6ec0797c0e4c3b323853390f15078e70 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 24 Jul 2023 21:16:05 +0200 Subject: Rewrite DeMorgan without str manipulation. --- crates/ide-assists/src/handlers/apply_demorgan.rs | 210 ++++++++++++---------- crates/syntax/src/ast/make.rs | 2 +- 2 files changed, 117 insertions(+), 95 deletions(-) diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs index 57cfa17cc8e..05847a864f3 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(); - - // 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 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, + }; + + 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_keep_pars_for_op_precedence() { + check_assist( + apply_demorgan, + "fn main() { + let _ = !(!a ||$0 !(b || c)); +} +", + "fn main() { + let _ = a && (b || c); +} +", + ); + } + #[test] - fn demorgan_doesnt_hang() { + fn demorgan_removes_pars_in_eq_precedence() { check_assist( apply_demorgan, - "fn f() { 1 || 3 &&$0 4 || 5 }", - "fn f() { !(!1 || !3 || !4) || 5 }", + "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 4c6db0ef06c..c240008e7af 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", ) }); -- cgit 1.4.1-3-g733a5 From 17f3055803f8d6551b746192a4ba78edb5b62995 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 8 Aug 2023 15:54:58 +0200 Subject: Rewrite DeMorgan v2 --- crates/ide-assists/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 05847a864f3..66bc2f6dadc 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)), -- cgit 1.4.1-3-g733a5 From 6aa03c5d1577b512ab6d339026fc6edf3233cd1a Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Wed, 9 Aug 2023 00:47:29 +0900 Subject: 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 eec57ba3f80..967e028bfb1 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 1c0f7b08da8..0348680e5da 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 8cbdae62526..8b352141084 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 0fb71135b4d..169679b4636 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 2837f400bce..20dccfafb38 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 9e30eed56f3..12f82640102 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 bf041b61f2f..964fa787583 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()), } }) -- cgit 1.4.1-3-g733a5 From 3bfe1d5d78e09aa1ba59b9d5740b211e7e0ce1a5 Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 00:04:55 +0800 Subject: 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 1b4ee4613d6..f6d6b00d740 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 133a488e1de..541cce8c5bf 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( -- cgit 1.4.1-3-g733a5 From 52b43927240ca8c77ef24b92a580b9e9291e17f8 Mon Sep 17 00:00:00 2001 From: ponyii Date: Fri, 30 Jun 2023 17:31:04 +0400 Subject: 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 540fa115a00..531a503c1b6 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 57f023ef35d..e2d24625cea 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 b3ca2a22258..1595622d2b2 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 2837f400bce..419a50ebe5f 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 de60c88844d..b577b3fb327 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 6aca716bb60..ea659a2295d 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 1d0cb426a57..cb04a0381bf 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 4c6db0ef06c..1eefd949050 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("{}") } -- cgit 1.4.1-3-g733a5 From 4ebdc6f0528365f32db4a529407d26a169c36617 Mon Sep 17 00:00:00 2001 From: ponyii Date: Mon, 10 Jul 2023 17:56:07 +0400 Subject: 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 ++- crates/ide-assists/src/handlers/extract_function.rs | 2 +- crates/ide-db/src/path_transform.rs | 7 ++++--- crates/parser/src/grammar/generic_params.rs | 2 +- .../err/0022_recover_from_missing_const_default.rast | 6 ++++-- .../parser/inline/ok/0188_const_param_default_path.rast | 15 ++++++++------- .../inline/ok/0199_const_param_default_expression.rast | 17 +++++++++-------- .../inline/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 531a503c1b6..7ee27d26709 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 e2d24625cea..c518f1b75b3 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 1595622d2b2..14346c27941 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 b577b3fb327..136b1b08533 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 7f61a68284c..1340681ccab 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 cb04a0381bf..507200ea3ba 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 8ed1c84c4c6..29d9b05d3f3 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 809ad1b8d5b..49f163b164a 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 11002bf98d0..3f5fb47d287 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 0607ff54fbb..d6501137498 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 8e52313651c..6de10353bf0 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 138ddd20897..ea7ebd85b33 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 0b27faa535d..16448db04f8 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 1eefd949050..217134385af 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 {{}}")) } -- cgit 1.4.1-3-g733a5 From 4e2be8e959179f8b7f9614e1d147b878bbd2f071 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 11 Jul 2023 18:46:39 +0400 Subject: 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 419a50ebe5f..a885c32e7f9 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 ea659a2295d..d9faf3a7f6c 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 507200ea3ba..efe13f06040 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); } -- cgit 1.4.1-3-g733a5 From 61cabe029fcd74aae6a2811768bc7f46f22354fe Mon Sep 17 00:00:00 2001 From: ponyii Date: Wed, 12 Jul 2023 18:31:40 +0400 Subject: 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 14346c27941..d0bb16c7808 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 d9faf3a7f6c..c0e5429a22c 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 efe13f06040..4bd4f1e845f 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()); } } -- cgit 1.4.1-3-g733a5 From e4c45427dc398f7fc8f984d2d1b454f36d718fd9 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 8 Aug 2023 21:51:59 +0400 Subject: 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 d0bb16c7808..405bb001b5d 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 a885c32e7f9..da5ee6fc428 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 136b1b08533..1d42e97aa3e 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 e52dc356775..e475c5cd66b 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 4bd4f1e845f..fb75b5b4584 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 f96ea29ae2f..a915391ad90 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)); } _ => {} } -- cgit 1.4.1-3-g733a5 From 68e8379ec35f83ce22d3c57bad79e8a7bc7ea231 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 8 Aug 2023 22:16:28 +0400 Subject: 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 7ee27d26709..1e2535a8a99 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 c518f1b75b3..75adf21abdc 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 { -- cgit 1.4.1-3-g733a5 From 6a2f83a8a25895922c477eb401f021f410904f9f Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 02:22:18 +0800 Subject: 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 9dfb98e459b..a701eb01192 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 de60c88844d..77cadfbae34 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 -- cgit 1.4.1-3-g733a5 From de86444756acc30878ed0ca95f686ff02b888b29 Mon Sep 17 00:00:00 2001 From: oxalica Date: Wed, 9 Aug 2023 02:42:08 +0800 Subject: 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 77cadfbae34..60ab0c267f4 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 a8e88369088..60fcbbbd397 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 7795be54e26..e3ad817e06a 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( -- cgit 1.4.1-3-g733a5 From 021802c59c03b664bb02a1be8eae73ca1114fa26 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 9 Aug 2023 00:27:23 +0330 Subject: 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 74c62a08a2b..7ad3659a4f6 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 9e30eed56f3..f2114e71211 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() { -- cgit 1.4.1-3-g733a5 From a1d9e453b9a273db44250baa5f2dc4f261617415 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 11:06:54 -0400 Subject: 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 5537673d1ee..90ad2ecaf91 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, } -- cgit 1.4.1-3-g733a5 From 0b57fa3931b88940678dcc0413fda4b4c97b4e93 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 20:09:50 -0400 Subject: 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 f2ed7247039..273716bd513 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: convert TypeLocation::GenericArg to struct variant --- crates/ide-completion/src/completions.rs | 2 +- crates/ide-completion/src/completions/type.rs | 51 +++++++++++++-------------- crates/ide-completion/src/context.rs | 21 ++++++++--- crates/ide-completion/src/context/analysis.rs | 15 +++++--- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 125ebc98a52..7e2ecdbb858 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 621dea0b9a5..a30fd13b1d5 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(); - - 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 + 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 } } } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 90ad2ecaf91..1fd635ba2e7 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 2064ae34dd9..c66cb987fea 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, -- cgit 1.4.1-3-g733a5 From fb98f522d216ee0c28b56115b130c5374c444ed9 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Tue, 8 Aug 2023 20:55:35 -0400 Subject: 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 273716bd513..d518dd76410 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; -- cgit 1.4.1-3-g733a5 From 18b24f60d0423a7b88978ca08bcfca4a905583d1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 14:09:37 +0200 Subject: 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 f51ea7eeb22..13463e9f72e 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()..) -- cgit 1.4.1-3-g733a5 From 992b928a930c58348c55263e13f140c06912e58d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 15:20:42 +0200 Subject: 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 | 292 +++++++++++++++----------- crates/hir-def/src/nameres/path_resolution.rs | 21 +- crates/hir-def/src/resolver.rs | 10 +- 7 files changed, 216 insertions(+), 156 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 91db68058b0..68defa3858f 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 df2af4c89b0..59c250d7506 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 1901db8a0f9..c40bbc0380e 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 86818ce26dd..5c99f691a64 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 eef54fc492e..f79f4ab0ba9 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"); - - let res = self.resolve_extern_crate(name); - - match res { - Some(res) => { - PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public)) + 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); + + match res { + Some(res) => PartialResolvedImport::Resolved(PerNs::types( + res.into(), + Visibility::Public, + )), + None => PartialResolvedImport::Unresolved, } - 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. - ); + 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. + ); - let def = res.resolved_def; - if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() { - return PartialResolvedImport::Unresolved; - } + 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)), - ); + 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) + // 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); - } - } - - // 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); - } + 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) + }; - 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 de22ea10146..64cdbdce770 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 d04d2fa0e97..17a1bf50b5e 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()); } -- cgit 1.4.1-3-g733a5 From c516dd51e9eb53e7d4275d1f1d543dce643e492a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 15:54:10 +0200 Subject: 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 f79f4ab0ba9..9a7e6bdcc8a 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. -- cgit 1.4.1-3-g733a5 From 4e4dda5f59ca6c07a8fe111ff5c0e33caa12a907 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 16:40:23 +0200 Subject: Deunwrap convert_named_struct_to_tuple_struct --- .../ide-assists/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 fe1cb6fce36..76f021ed912 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; -- cgit 1.4.1-3-g733a5 From b658f9a9548315801d3f0a706ccd32b9c772a33e Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Wed, 9 Aug 2023 17:54:34 +0300 Subject: 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 a403d5bc672..e2b82223289 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 { -- cgit 1.4.1-3-g733a5 From 63aba76735c387c15230039b9ac7712a18962cb7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 17:06:52 +0200 Subject: 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 9a7e6bdcc8a..92d5cdd09bd 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, -- cgit 1.4.1-3-g733a5 From ebf27058cd84c116bf6dc6c8b06d589e97eda165 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 17:17:43 +0200 Subject: 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 dcb96ab8af4..7d0e424769e 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( -- cgit 1.4.1-3-g733a5 From 7e04142f25761f9555553081fc9e38e605579184 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 9 Aug 2023 20:06:08 +0200 Subject: 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 701fee40ab2..1495cc68e3f 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 5bfac7ee45c..1f9d6db9314 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" -- cgit 1.4.1-3-g733a5 From c81a0681a26c557e2f46dcb1876fcafa24d569b3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 23:42:52 +0200 Subject: Deunwrap generate_delegate_methods --- crates/ide-assists/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 31fc69562c9..bbac0a26ea4 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(); -- cgit 1.4.1-3-g733a5 From 423b00a83a72c9468dde600ace59ed14ae0f77a5 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 10 Aug 2023 01:22:26 +0200 Subject: 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 dd4839351fb..5fcab8c02b0 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 { -- cgit 1.4.1-3-g733a5 From 94b3481808e5033cf45800cc9e22e15d5245aa1a Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 10 Aug 2023 01:46:51 +0200 Subject: Deunwrap generate_derive --- crates/ide-assists/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 747f70f9f6f..5e67537c80b 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); } }; }) -- cgit 1.4.1-3-g733a5 From e5b23e3bc1ad9c5ea70922c74ce9bba4f4dcf299 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 18:52:27 +0200 Subject: 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 fae07111806..75607e51732 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 3853a6ab3a5..889544e151f 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 e34a6768f28..5d2edf9f304 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 1495cc68e3f..62292779571 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 e719f9291bd..f8efc802234 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 5c99f691a64..2785b98fd6a 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 4c918e55b92..0ec2422b30c 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 3308077da5b..691d0c618f3 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)] -- cgit 1.4.1-3-g733a5 From fde2d9b47c1ca1a5b4c816e72acb784f7731f03e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 19:04:46 +0200 Subject: 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 75607e51732..a5db75a91eb 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 2785b98fd6a..9dc595ee7ee 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 92d5cdd09bd..410bbe02535 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, -- cgit 1.4.1-3-g733a5 From bfad781a77cf2eb945694718e9cb3ab2830ecb28 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 19:22:46 +0200 Subject: 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 5d2edf9f304..31c1a713031 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 62292779571..5734f1c67b6 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), } } -- cgit 1.4.1-3-g733a5 From 9adff006e884287f3924cd599dcdb0fe58308623 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 20:10:19 +0200 Subject: 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 5734f1c67b6..957a5cf2e2b 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 9dc595ee7ee..f93125e224d 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 410bbe02535..e3253404d49 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 1f1e20f49e3..ba14553d90e 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 9eaa9e1c2f5..7ab0c1f7f2f 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 b1c00d816f8..46def6c052f 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 } => { -- cgit 1.4.1-3-g733a5 From 0ef541e535c9d301a62fe039c6904e4d82a5c824 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 8 Aug 2023 14:15:29 -0700 Subject: 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 38ce6761578..0ddb2922198 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, _) => { -- cgit 1.4.1-3-g733a5 From 687bffa49375aa00bacc51f5d9adfb84a9453e17 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Mon, 7 Aug 2023 14:24:41 -0700 Subject: 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 ++++++---- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 76 +++++++++++++--------- compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | 14 +++- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/debuginfo.rs | 2 +- .../codegen/debuginfo-inline-callsite-location.rs | 26 ++++++++ 7 files changed, 106 insertions(+), 51 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 a81585d4128..d1bfd833cd8 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 d174a3593b9..7a68c291aa5 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 40714a0afe9..d03819b1688 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); - - 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 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, - ) - } + 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 (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, + ) + } + }) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 4167a85ccd5..b9d5b54dc62 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 3464f910829..ccf93f208d5 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 63fecaf34fd..4acc0ea076c 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 00000000000..e2ea9dda4a0 --- /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 +} -- cgit 1.4.1-3-g733a5 From c1c8e787d22b06bff095b261e3f2e6c539cf590e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 10 Aug 2023 20:11:03 +0200 Subject: 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 169679b4636..0a68a9f3b58 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>( -- cgit 1.4.1-3-g733a5 From d6d188fce2f2dec3b6d290477c7727b420b0c320 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 06:32:23 +0200 Subject: 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 b54c43b296b..ad1ce453eca 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 d1479dd1e58..0740bfbc7b1 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, -- cgit 1.4.1-3-g733a5 From 33f9250d2139fa00038736515b9e22c51c419c01 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 07:10:20 +0200 Subject: 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 ef4dff095cf..6cf399599d9 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 38ce6761578..e5394525772 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); -- cgit 1.4.1-3-g733a5 From 9ac88d8d36b0e53ace1d67e98ec7c38363cd76d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 11 Aug 2023 09:58:55 +0200 Subject: Fix parser being stuck in eager macro inputs --- crates/hir-def/src/body/lower.rs | 3 ++ .../src/macro_expansion_tests/builtin_fn_macro.rs | 2 +- .../src/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 3853a6ab3a5..3389fdfb15e 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 1250cbb742c..b232651db96 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 b783de4ccc2..97554f93f1c 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 333318f53b7..6a2a9adce15 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![,]); } -- cgit 1.4.1-3-g733a5 From 90dc2f839b05bf0467bac71d9be738eab6423dc7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 12 Aug 2023 02:13:37 -0700 Subject: 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 a53b8535213..878b13581ac 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 a1cec22c97a..e12cdb1b4ec 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 /// -- cgit 1.4.1-3-g733a5 From d51521e28044edcff0a1f7666629e5e7aea73727 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:48:55 +0100 Subject: Add warning block support in rustdoc --- src/librustdoc/html/static/css/rustdoc.css | 26 ++++++++++++++++++++++--- src/librustdoc/html/static/css/themes/ayu.css | 1 + src/librustdoc/html/static/css/themes/dark.css | 1 + src/librustdoc/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 b1de8c1529e..da4da50106a 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 d8dae51eb1b..c81a80eeca0 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 2b302988734..0f8b1dc24a6 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 56fd8cbef12..39ea44a1165 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; -- cgit 1.4.1-3-g733a5 From 57d2b84a57225717c6af8748574b4a847d62433c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:49:11 +0100 Subject: 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 1fa9f814476..aaabaa6098f 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/ -- cgit 1.4.1-3-g733a5 From 1d42913058d4005655ea51b2d9dde707791c6541 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Jan 2023 14:50:03 +0100 Subject: Add GUI test for warning blocks --- src/doc/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 aaabaa6098f..acab1a93690 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 49484ee0869..38180aef762 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 00000000000..2a935bd1a9b --- /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)", +}) -- cgit 1.4.1-3-g733a5 From e76d20e072cd25ca2df21ef51e973bf666f4c840 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 12 Aug 2023 08:25:51 +0200 Subject: 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 96fc8d7ecf0..83460c82c11 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 e21f536f26a..aba37bac27d 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 0e64054c11d..39e2f767c76 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 16c14ca54f2..363a7a82e68 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 448150bac06..ee5e5b1b80c 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 e5394525772..1e83c281a13 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 { -- cgit 1.4.1-3-g733a5 From 4c67becd44ee47ec4f966f1173b410647875bb65 Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Tue, 15 Aug 2023 17:35:29 +0300 Subject: Always collect memory usage info in analysis-stats --- crates/profile/src/stop_watch.rs | 20 +++++++------------- crates/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 71303d5a631..814a0257402 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 f446a7c0596..4a03be1893c 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 13b7f039bb0..419440b6df7 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 68537423195..e4710260409 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()); } -- cgit 1.4.1-3-g733a5 From c737c62e70cf8627e01e0b3a1088e96bff1b154d Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 15 Aug 2023 16:03:17 +0200 Subject: 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 40cbf14958e..6bc0b346d92 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 } - } - #[cfg(not(parallel_compiler))] - { - 0 + if is_dyn_thread_safe() { + return Sharded::Shards(Box::new( + [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))), + )); } - } - #[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> { -- cgit 1.4.1-3-g733a5 From fec5ff989025ee01f7659da28e95d0fe0feafa86 Mon Sep 17 00:00:00 2001 From: ponyii Date: Tue, 15 Aug 2023 20:26:42 +0400 Subject: 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 a701eb01192..ac171026d5d 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 541cce8c5bf..d0f9f7b0e16 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 ``` "#]], ); -- cgit 1.4.1-3-g733a5 From 2a78173ff86753bfe9525943925a98d2636c6da1 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 16 Aug 2023 00:22:08 +0200 Subject: v2 --- crates/ide-assists/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 5e67537c80b..53ba144ba9e 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."), + ); } }; }) -- cgit 1.4.1-3-g733a5 From 81220c0acef24bd88e960a9b2c2eea3140365864 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 16 Aug 2023 10:00:25 +0200 Subject: Keep SHARDS fixed instead of a function of `cfg!(parallel_compiler)` --- compiler/rustc_data_structures/src/sharded.rs | 23 ++++++++++++++++++---- compiler/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 6bc0b346d92..39cce5c8ee6 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 30422ea1102..0d4d13ac20d 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(), ) }), -- cgit 1.4.1-3-g733a5 From 53b292478d1f25209d90a6f657066e45989f3b3e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Aug 2023 10:07:18 +0200 Subject: 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 +- .../ide-assists/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 ba14553d90e..4be55126b86 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 e99d2984c36..25b5bd365e3 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 4f3b6e0c287..c3d925cb26c 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 1340681ccab..ea7a21e77a4 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 1eb8f00020b..330af442f75 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 d5abd099126..7e00d368652 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 dd1d0d75c63..f834f2ce592 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 d240127f376..901f7a2a79a 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 d6bbf2bf794..119a9c7c3f4 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 f9061822244..3d89599c583 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 c39c696cfd9..7e0fab42608 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 21471ab2a03..e09b9f39148 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 37166bdbd0c..544c6b42317 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 6048990f749..955923d7691 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 43e89a334bf..46a0464e9e6 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 40659e6c263..21934b9480e 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 bf77d55d58e..c9cdbff7d7d 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 17f3771b1a5..2ca2b5b1d5f 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 813f9ed943f..2d0295692ac 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 e3ad817e06a..847ab3d21ad 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 ae97236409e..bb01c81d66f 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) { -- cgit 1.4.1-3-g733a5 From 0823f0c32b600dafcc707e76dc1898eadc3c2b59 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 16 Aug 2023 10:44:32 +0200 Subject: 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 39cce5c8ee6..52ab5a7fb14 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(), + } } } -- cgit 1.4.1-3-g733a5 From af8048266cd87e7855cb150803260887aa93d01a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Aug 2023 11:18:11 +0200 Subject: 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 +- crates/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 59c250d7506..234d3eaed56 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 d742b2eef0a..5d7bb0b49d7 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 873accafb43..03fc5c3abde 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 c40bbc0380e..3c0ed8c2e51 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 f93125e224d..f2110410980 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 e3253404d49..b6658e4552c 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 64cdbdce770..fc296e1e588 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 40d3a16540d..4a86f88e57a 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 2bc1f8e926e..f32a97d1a3a 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 17a1bf50b5e..28ab0f8f6ee 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 f27ed485d81..ac3511ba47b 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 } -- cgit 1.4.1-3-g733a5 From 42a708083a59ece9599723f69536ddb6e987e6e4 Mon Sep 17 00:00:00 2001 From: Georgii Rylov Date: Thu, 10 Aug 2023 14:06:41 +0100 Subject: 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 dbad425976a..99717613f57 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() } -- cgit 1.4.1-3-g733a5 From 9b00e5f06f51703c5294af602959d3f92c095aa7 Mon Sep 17 00:00:00 2001 From: Georgii Rylov Date: Wed, 16 Aug 2023 11:19:22 +0100 Subject: 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 99717613f57..a0eefa8811a 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() } -- cgit 1.4.1-3-g733a5 From c4e9b5ac649c62a46110660b612776468ba0d07f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 09:33:15 +0200 Subject: Add import info to item scope dumps --- crates/hir-def/src/body/tests/block.rs | 20 +- crates/hir-def/src/item_scope.rs | 240 ++++++++++++++++----- 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 ++--- crates/hir-def/src/nameres/tests/mod_resolution.rs | 32 +-- crates/hir-def/src/nameres/tests/primitives.rs | 4 +- 8 files changed, 360 insertions(+), 211 deletions(-) diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs index 4e015a7fbbb..44eeed9e3fb 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 03fc5c3abde..59a1c5f49e2 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()); + 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()); + } + _ => _ = 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) } - ImportType::Named => { - $glob_imports.$field.remove(&$lookup); + 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; + } + } + _ => {} + } + } - entry.insert(fld); - $changed = true; + 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()); } - 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.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; } } - }}; + _ => {} + } } - 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.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 b6658e4552c..48eaec0f4e5 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 dd7c3c36306..e7cc44b04da 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 88a3c76393f..1ca74b5da6b 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 f4cca8d68d0..e64fa0b46f1 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 81bc0ff91e3..1327d9aa62e 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 215e8952d90..271eb1c79b1 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 "#]], ); } -- cgit 1.4.1-3-g733a5 From a17d73ad36baaec68078fe8b44c0b43e94a8e46a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 10:52:13 +0200 Subject: Thread imports through the resolver --- crates/hir-def/src/item_scope.rs | 60 ++++++++---- crates/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 +- crates/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 59a1c5f49e2..0baf3fa7f44 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 7a87e61c693..8adced4e082 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 48eaec0f4e5..e9e71a8747f 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 fc296e1e588..460a908b6db 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 f32a97d1a3a..3f3f9f42491 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 28ab0f8f6ee..62576100ea4 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 9f9a56ffab0..cbca0e801d4 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 b4915dbf0f9..0fb4934444b 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 1781f6c58f1..23efe616f4f 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 79d9e21e797..2a51c84db3a 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 20dccfafb38..0ab04b83cf8 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 7ab0c1f7f2f..51cf882d053 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 3354cbd76a0..1cdfd919742 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 e99d2984c36..55760ba75ab 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 3499daf1140..f29fb1edf00 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) } -- cgit 1.4.1-3-g733a5 From 637f496a814ec850e3a18064c648e0835f56c90c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 12:17:41 +0200 Subject: 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 234d3eaed56..b60e7909105 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 5d7bb0b49d7..c961d7d86d8 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 0baf3fa7f44..699231fd378 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 3c0ed8c2e51..3f87fe62b83 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 3f3f9f42491..da9c13740b3 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 cd0410168c2..364405f56a8 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 8c038c0fbaa..4cdfd546f6a 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) + "#]], + ); +} -- cgit 1.4.1-3-g733a5 From eb6244c5f91884a612c2fd16a2a5439237129f64 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 18 Aug 2023 11:46:35 +0200 Subject: 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 +- .../src/test_data/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 699231fd378..7c11fb9d136 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 957a5cf2e2b..3e1922750b9 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 f8efc802234..e4702c113b8 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 da9c13740b3..14890364d0b 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 6047f770d4d..3770103cda5 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 364405f56a8..121e5a0a249 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 583e26c136c..512fe7e0428 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 43d957412bc..ca7874c3683 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 ad1ce453eca..f699f999baf 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 1a00e29384e..87ad5844c64 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, + }, ], ), ] -- cgit 1.4.1-3-g733a5 From 132a2c6cf29649d0b57f3efe9fe72beef8fc7c9e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Aug 2023 12:49:07 +0200 Subject: 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 ca908671ae5..30403a61442 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) } } } -- cgit 1.4.1-3-g733a5 From dadbfe7f4bc0153214caf5febb08b148ad64acc0 Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 13:36:07 +0100 Subject: 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 f8806794979..26b62181630 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 f6a50bfa6b2..12425b6756f 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 = [ -- cgit 1.4.1-3-g733a5 From 6c46b98a9532b93c538b3553a7ff6ab4aa50655c Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 13:41:13 +0100 Subject: 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 26b62181630..d0f5abd8fd4 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 12425b6756f..44f01ac832d 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 01707d30191..e1c49db39d5 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] -- cgit 1.4.1-3-g733a5 From 1cebc0ca13b5e818e6c5a1b6a5e6ddf9008d433d Mon Sep 17 00:00:00 2001 From: Alex Kladov Date: Sat, 19 Aug 2023 15:28:32 +0100 Subject: 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 d0f5abd8fd4..9e838fcc880 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 44f01ac832d..5eb59d6db11 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 = [ -- cgit 1.4.1-3-g733a5 From acd3542b8d4cf9b4bc1cf6c99f76bb2fb938fe20 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 19 Aug 2023 18:47:08 +0000 Subject: 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 5e8ba4f544c..603a829412b 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 00000000000..54a22510066 --- /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 00000000000..51d28704972 --- /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() {} -- cgit 1.4.1-3-g733a5 From fad7d220fd2daefe8ee778b8cafbbeaf2dda4fc5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 19 Aug 2023 23:27:50 +0000 Subject: 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 +++++++++++++++------- .../infer-placeholder-in-non-suggestable-pos.rs | 2 + ...infer-placeholder-in-non-suggestable-pos.stderr | 16 ++++- tests/ui/consts/assoc-const-elided-lifetime.rs | 19 ++++++ tests/ui/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 f73797415bc..aabefb729f3 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 96c31a90da8..0aa37642b74 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 f350957f72f..d68d0847254 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 c87db96a5dd..22d084c8e0b 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 40896c32e11..1e0b77b0d3b 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 993a08faba9..f8c02420f96 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 00000000000..10cd33a8fed --- /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 00000000000..a1eeaff4ba8 --- /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 + -- cgit 1.4.1-3-g733a5 From 4170ca4be92f1a8e4bfd1d2815c12804710b7087 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Sun, 20 Aug 2023 01:59:44 +0200 Subject: 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 2a23a69b584..e614046e83e 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); -- cgit 1.4.1-3-g733a5 From 1f7bad0d128c6b005ffadb683fffb8cc02f66c7d Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Sun, 20 Aug 2023 13:22:39 +0000 Subject: 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 81a6914815e..ffcaac176c5 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 a68d4945d82..7bbb8ed2ca9 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 68cfce4065c..7ffe1287eb3 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 -- cgit 1.4.1-3-g733a5 From 37e0e8af10514a2064915389f22743fb690e3f93 Mon Sep 17 00:00:00 2001 From: Jessie Chatham Spencer Date: Thu, 30 Mar 2023 08:53:36 +0200 Subject: Implement extern crate completion --- crates/hir-def/src/resolver.rs | 19 ++++++ crates/hir/src/semantics.rs | 8 +++ crates/ide-completion/src/completions.rs | 2 + .../ide-completion/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 62576100ea4..2f9187009e2 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 65ccb8b0733..b8d4ecd4414 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 7e2ecdbb858..f60ac150164 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 00000000000..0d0e143f5f6 --- /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 1fd635ba2e7..0da7ba6d000 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 c66cb987fea..1e6b2f319aa 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 { -- cgit 1.4.1-3-g733a5 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: 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 ad02ca252c4..bd0ab6463f0 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 00000000000..e0df96b0de8 --- /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() {} -- cgit 1.4.1-3-g733a5 From 82ce7b14613c4703e2a21775c60c578ac9246db2 Mon Sep 17 00:00:00 2001 From: Sebastian Toh Date: Thu, 3 Aug 2023 11:39:03 +0800 Subject: Add note when matching on tuples/ADTs containing non-exhaustive types --- .../src/thir/pattern/check_match.rs | 45 ++++-- .../integer-ranges/pointer-sized-int.deny.stderr | 4 + ...-85222-types-containing-non-exhaustive-types.rs | 67 ++++++++ ...22-types-containing-non-exhaustive-types.stderr | 170 +++++++++++++++++++++ .../non-exhaustive-pattern-witness.stderr | 2 + .../usefulness/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 383e80851f0..f46cf0dc0ff 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 0e0f0c3e11e..df330c60b1e 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 00000000000..8f58227ee2c --- /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 00000000000..ea1d99e20ae --- /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 b8af566de7c..d798ec722dd 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 e2a65ff8524..50c7fc889f4 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), -- cgit 1.4.1-3-g733a5 From 887cc48ba8929f7fcc3d43258d5b7c76b1e2f8ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:21:06 +0200 Subject: 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 4a31e0ba0a3..40c50f6d176 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 820535cc1b0..71feed0f72c 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 83460c82c11..44f1b81675a 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": [ -- cgit 1.4.1-3-g733a5 From 07b57f9a7a7c532497215e7973ae54d479f68cf9 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin Date: Mon, 21 Aug 2023 12:51:51 +0300 Subject: 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 ++ .../issue-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 967ad3a0e69..9d9743a4378 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 093dcbbe8bf..aa3b7b7e191 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 2fff3f0efd7..732fcce0f29 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 9a93bb72903..5f5d931a267 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 85e88287094..659b5465522 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 246de2f5e4b..cfc6c4450b4 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 3b518d1802b..d1f5ea3602a 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 -- cgit 1.4.1-3-g733a5 From fd2982c0a7bf1bc52685547849ba1d96c93d69c9 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 21 Aug 2023 18:45:02 +0700 Subject: 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 46b773bdc50..344ac221698 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! ``` -- cgit 1.4.1-3-g733a5 From 44cc3105b13f0e2dcc9aec8d019dc40011104bc5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:55:27 +0200 Subject: 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 19061742b64..2ae334c6a95 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 -- cgit 1.4.1-3-g733a5 From dfbac25fbadd9f417ac207838cae291c6cbc6f46 Mon Sep 17 00:00:00 2001 From: Christiaan Biesterbosch Date: Mon, 21 Aug 2023 14:25:57 +0200 Subject: 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 371ee378d1a..bd33b8fb6cc 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 8bc9381342d..f8cd92f9257 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. | -- cgit 1.4.1-3-g733a5 From 53245709f68280943b4d2a3995883fc1b90087f9 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 21 Aug 2023 18:32:58 +0700 Subject: 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 eb46f4e54bb..873bfb6218b 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")] -- cgit 1.4.1-3-g733a5 From 5dce0e66b9424ed1070e5b37ca21ffee62957595 Mon Sep 17 00:00:00 2001 From: allaboutevemirolive Date: Mon, 21 Aug 2023 13:31:58 -0400 Subject: 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 f350957f72f..1d0e367abba 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" } -- cgit 1.4.1-3-g733a5 From 88bd304a1000be95e15c319ca79564e168ba02c3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 21 Aug 2023 10:06:05 -0700 Subject: 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 a659b552f47..776899dbcfd 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 721e1fb754e..4f4f5f02471 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")] -- cgit 1.4.1-3-g733a5 From ea9e442222ed256c8ac70693d5966dd9fe2bde4b Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 12:53:39 -0700 Subject: 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 ac9c180a6a8..0eddaec2999 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 6cab3498622..a4af1c25cfc 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 254b0d8bf5a..cb653d6b8df 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 91082483948..5d2c553d8a5 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 b0c22540180..3b836a21931 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 45a6ba8ed2e..4c8a0f543a5 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 e1feb1cd64f..f6a059de620 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; -- cgit 1.4.1-3-g733a5 From bf766cd31bf045dfe7f37d4146f36aff001438ed Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 21 Aug 2023 19:59:27 +0000 Subject: 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 00000000000..3853bc8594f --- /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 00000000000..8bea440ddba --- /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`. -- cgit 1.4.1-3-g733a5 From 89e6597dfe12b40c72ca4c3d479568e3a4ec1e7a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 21 Aug 2023 13:13:44 -0700 Subject: 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 371ee378d1a..206471d9035 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 -- cgit 1.4.1-3-g733a5 From 062d247cd795847be51df9e3f818f0eb52ac0d18 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 13:56:22 -0700 Subject: 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 +++++----- src/librustdoc/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 cac21130740..cc86a3d7475 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 ee1d0be27bf..1e85284371d 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 49bde1d3152..9cf3c068b60 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 656aeefb01a..ceba643ed5f 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 d1deda0c716..9a34e7cce8a 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 a788935581f..fd79160ff4a 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 0eddaec2999..a98b59c6181 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 a4af1c25cfc..cb78f903462 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 f3da610565c..b96b1536156 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 8673138f649..f857a4c8a49 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 e732a405760..96224d7c6e2 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 64a4ace5b9f..b3561841594 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 390b9436121..01e6cb4b93b 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(_) -- cgit 1.4.1-3-g733a5 From c90a5b2019e5a862c8fb5ae39dcf6ad5f4c65b09 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 14:01:26 -0700 Subject: 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 a98b59c6181..aef8f1a74fb 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 f857a4c8a49..66b5798797f 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 cd791ce000b..27e8a27ba2f 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 ba8eeaa6682..5d979521885 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 45a9c93ee0b..d48e6533a20 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 bf8a64acf08..79b1551f301 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_); } -- cgit 1.4.1-3-g733a5 From 3df9b4d65d7230911b3ca826a62788d65f7a3001 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 21 Aug 2023 12:05:45 -0700 Subject: rustdoc: use unicode-aware checks for redundant explicit link fastpath Fixes #115064 --- src/librustdoc/passes/collect_intra_doc_links.rs | 11 +++-------- src/librustdoc/passes/lint/redundant_explicit_links.rs | 7 +------ .../rustdoc-ui/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 36872266ee1..7b0a7a90d31 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 ef0f8716aa8..67cd2cc9732 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 00000000000..fecefb7b25f --- /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; -- cgit 1.4.1-3-g733a5 From d9f7005ab6e8376417ff115b569498907b5c787c Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 22 Aug 2023 00:50:25 +0200 Subject: 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 9f2ff437842..6f0e544a597 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 } -- cgit 1.4.1-3-g733a5 From 4d9ac5df59f400e76ce7532fa1b6b459d4a1c70c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 21 Aug 2023 16:20:00 -0700 Subject: 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 574cc629a04..913d72932b9 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" -- cgit 1.4.1-3-g733a5 From b1c609e2a6716cb76d2690d86d2d9c255cacbb18 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 21 Aug 2023 20:43:04 +0000 Subject: 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 e6d27757ac6..07ff3da6b4a 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 75e7a3fec00..3f8b5a08969 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) -- cgit 1.4.1-3-g733a5 From 0383131f7f48c7ff65b982c4c07dd8a7e6d5ed5e Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Tue, 22 Aug 2023 00:00:00 +0000 Subject: 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 f9d34ea71ba..e62833b358b 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 3b664f43654..5e172ef3198 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 2e893c5d9bf..0b50c41fc5e 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(); } -- cgit 1.4.1-3-g733a5 From e41240e45b58ea1bcf42fe5503cafec4c9dca1a8 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 22 Aug 2023 02:36:41 +0200 Subject: Fix races conditions with `SyntaxContext` decoding --- .../rustc_data_structures/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 8c84daf4f16..27d687c3cfe 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 9f2ff437842..37ec2f0801c 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( -- cgit 1.4.1-3-g733a5 From 28de139d3545ec7e98dcb0e56349c0d5af0c3909 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 08:48:39 +0200 Subject: 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 d0d62db0807..db3b7ffbea4 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")); -- cgit 1.4.1-3-g733a5 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: 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 9942c70c4ae..0c5f6ff7a79 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) => { -- cgit 1.4.1-3-g733a5 From ddf89a877601b9e16d777e7b5d06d2ae32e56929 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 22 Aug 2023 08:05:00 +0000 Subject: Remove myself from review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index a06195cc334..b5047fd4344 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -505,7 +505,6 @@ compiler-team-contributors = [ "@TaKO8Ki", "@WaffleLapkin", "@b-naber", - "@fee1-dead", ] compiler = [ "compiler-team", -- cgit 1.4.1-3-g733a5 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: 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 0c5f6ff7a79..76b493353cc 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) => { -- cgit 1.4.1-3-g733a5 From 0e070aa548e32f6ba8dd4cc28e9c71d9ccfb7ff3 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 22 Aug 2023 09:09:12 +0100 Subject: 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 f44a05a6b28..c5c70f2e18a 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 a4135b06e9d..52162bf42ea 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."); -- cgit 1.4.1-3-g733a5 From 1fac8a0eab870f25fa4c8ab21f0e14e54cdda4a4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 22 Aug 2023 20:30:19 +1000 Subject: 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 +------------------------- compiler/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 7e8ac9a141a..69909fcea0a 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 c16bd6cbd70..a2ab51ff846 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, -- cgit 1.4.1-3-g733a5 From c8522adb9709cc62123fe4e68082abf90cdffc62 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 21 Aug 2023 09:12:15 -0400 Subject: 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 f5708f933d5..f5bc140c049 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 afed3fdf745..c485680f92e 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 476a4fea54f..d3b7558440c 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 81148c7cc51..23ca37817d4 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 9582ca9e0be..e0fd347a049 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 49f9f6d4ad1..2b37af66bd6 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 b0484474712..ee9f6ed087c 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 a7e65305386..4094e378034 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 3840ffe7eec..6bc8f181c90 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 88326aaf295..029de8fbf76 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 f54d5934175..7380b45b00f 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 21515adc6c4..09994e47f0a 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)) } -- cgit 1.4.1-3-g733a5 From 068e3d97d0f1da0019e6e98dbd151d5e9df548b1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 22 Aug 2023 06:58:03 -0400 Subject: 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 5f54504b8ea..201f9a0c612 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" } } -- cgit 1.4.1-3-g733a5 From d2744175ac1620cc094fcb842c9c60c8889ea603 Mon Sep 17 00:00:00 2001 From: mojave2 <0109chenchen@gmail.com> Date: Fri, 18 Aug 2023 14:49:01 +0800 Subject: 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 ++--- .../warn-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 4cf3587327d..d8331661366 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 1f4e5fa4d3b..0a40d17f98e 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 b07c6db599e..e06b6380944 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 78940462b2c..5f8bbfca890 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 1cf63e9b7ba..671204c0d8e 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 aa73b824a57..32f8d2f45dc 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 82851c80064..dd9ecf02fa6 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 -- cgit 1.4.1-3-g733a5 From 265c1b5d5025a1cb3bdc26b99f35317079a55c36 Mon Sep 17 00:00:00 2001 From: kadiwa Date: Tue, 22 Aug 2023 14:43:53 +0200 Subject: add regression test for not memcpying padding bytes --- tests/codegen/box-maybe-uninit.rs | 32 --------------------------- tests/codegen/box-uninit-bytes.rs | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 32 deletions(-) delete mode 100644 tests/codegen/box-maybe-uninit.rs create mode 100644 tests/codegen/box-uninit-bytes.rs diff --git a/tests/codegen/box-maybe-uninit.rs b/tests/codegen/box-maybe-uninit.rs deleted file mode 100644 index 282af99b067..00000000000 --- a/tests/codegen/box-maybe-uninit.rs +++ /dev/null @@ -1,32 +0,0 @@ -// compile-flags: -O -#![crate_type = "lib"] - -use std::mem::MaybeUninit; - -// Boxing a `MaybeUninit` value should not copy junk from the stack -#[no_mangle] -pub fn box_uninitialized() -> Box> { - // CHECK-LABEL: @box_uninitialized - // CHECK-NOT: store - // CHECK-NOT: alloca - // CHECK-NOT: memcpy - // CHECK-NOT: memset - Box::new(MaybeUninit::uninit()) -} - -// https://github.com/rust-lang/rust/issues/58201 -#[no_mangle] -pub fn box_uninitialized2() -> Box> { - // CHECK-LABEL: @box_uninitialized2 - // CHECK-NOT: store - // CHECK-NOT: alloca - // CHECK-NOT: memcpy - // CHECK-NOT: memset - Box::new(MaybeUninit::uninit()) -} - -// 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]+]] - -// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} } diff --git a/tests/codegen/box-uninit-bytes.rs b/tests/codegen/box-uninit-bytes.rs new file mode 100644 index 00000000000..732da0a1794 --- /dev/null +++ b/tests/codegen/box-uninit-bytes.rs @@ -0,0 +1,46 @@ +// compile-flags: -O +#![crate_type = "lib"] + +use std::mem::MaybeUninit; + +// Boxing a `MaybeUninit` value should not copy junk from the stack +#[no_mangle] +pub fn box_uninitialized() -> Box> { + // CHECK-LABEL: @box_uninitialized + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} + +// https://github.com/rust-lang/rust/issues/58201 +#[no_mangle] +pub fn box_uninitialized2() -> Box> { + // CHECK-LABEL: @box_uninitialized2 + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + 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]+]] + +// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} } -- cgit 1.4.1-3-g733a5 From 7ee77b5d1b91adf4c683d0d871015fe68ebca9ea Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 22 Aug 2023 15:41:07 +0200 Subject: 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 2577cabb3f0..883f6242b56 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 28a2dfebcfe..8aec12f128e 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 5f094ac4e7e..01e36044899 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 6c38bca3daa..92d985948ec 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 7ff9b76a85e..c1589f13835 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 -- cgit 1.4.1-3-g733a5 From d5269a1d7ba86896be6ad158530f7787272c46f9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 22 Aug 2023 16:15:00 +0100 Subject: 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 b5047fd4344..2f380ef1dda 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"] -- cgit 1.4.1-3-g733a5 From 6aef5b331ffcb6816fb8900f5e2d87948e7cff84 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Tue, 22 Aug 2023 15:29:10 +0000 Subject: 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 4821d20a898..762e66ac7cc 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(); -- cgit 1.4.1-3-g733a5 From b86285af1661abb0824ead4ea89db0e5c898c422 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 21 Aug 2023 21:01:27 +0000 Subject: Do not emit invalid suggestion in E0191 when spans overlap Fix #115019. --- compiler/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 bd311c98fac..6082d446979 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 8bea440ddba..61299550e98 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 -- cgit 1.4.1-3-g733a5 From 3977ed1e69e6fc14e76e19bead3d6d725fc2129d Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 22 Aug 2023 12:26:35 -0400 Subject: 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 35d6b9ed7a4..54fdc84c77d 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()); -- cgit 1.4.1-3-g733a5 From 35187c7e6474d346eea3113c4ae34d26d6b18756 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 10:42:12 -0700 Subject: 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 db3b7ffbea4..d1018978f78 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), -- cgit 1.4.1-3-g733a5 From 015b5cb3066a85eee4524762f8bc7cf00f09b3be Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 22 Aug 2023 13:01:37 +0300 Subject: 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 078ff67446f..ebacb7cce83 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 7e8ac9a141a..aea59c31379 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 2ae334c6a95..8e38e394b98 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 7a6601f09da..fe7fef5d0c1 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, +} -- cgit 1.4.1-3-g733a5 From 1097e0957e299613fac4ea58c85aaf8204075a62 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 22 Aug 2023 15:30:26 -0400 Subject: 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 d03819b1688..9cdeae2841b 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>, } -- cgit 1.4.1-3-g733a5 From ca055f148be2fb2ef1102c894330366be32c490f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 17 Aug 2023 11:16:20 +0100 Subject: Automatically add OS labels to std PRs --- triagebot.toml | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 2c71b650f68..e4bcb9361af 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", -- cgit 1.4.1-3-g733a5 From 4332e8417d15f304741208e82ab969768f0dc11d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Aug 2023 16:16:44 -0400 Subject: 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 c5c70f2e18a..c71ecc0a139 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 -- cgit 1.4.1-3-g733a5 From 3c6f4cc743316ff4b7f76a6492f78d6eb83dcf50 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Aug 2023 17:45:54 -0400 Subject: 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 c71ecc0a139..588164e4a85 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 4821d20a898..fc2c91f76b4 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 52162bf42ea..bf8cb4bd768 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 { -- cgit 1.4.1-3-g733a5 From 5ee08a0c9393bf94dc7d2943fdd2c2cd2b616c82 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 23 Jul 2023 12:00:58 -0700 Subject: 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 377d4a9ce5e..b3c5f41bdd7 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 17cd456b995..0d02636db91 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 3f1d5f3426a..0b2c09b3eed 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" -- cgit 1.4.1-3-g733a5 From 4c14ca3141e3adefa8d30a03d6050dbf9b6699bf Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 22 Aug 2023 12:20:35 -0700 Subject: 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 4ebbb16442e..7337901bc3a 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 e1c49fbd612..99faef833f8 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit e1c49fbd6124a1b626cdf19871aff68c362bdf07 +Subproject commit 99faef833f890fe89f1a959d89b951954118828b -- cgit 1.4.1-3-g733a5 From 42f993fd0239acc898d4a37af1beeff51d29940b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 15:24:35 -0700 Subject: 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 722f7e5dd08..242b1c2eefd 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) -- cgit 1.4.1-3-g733a5 From 4dd31a22a47e00eb70341205cb5260e10fabc2d8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 23 Aug 2023 01:06:48 +0100 Subject: Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 80eca0e58fb..2cc50bc0b63 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 80eca0e58fb2ff52c1e94fc191b55b37ed73e0e4 +Subproject commit 2cc50bc0b63ad20da193e002ba11d391af0104b7 -- cgit 1.4.1-3-g733a5 From 91cf04d2072a463759173f0173da2a44faadeb20 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 23 Aug 2023 00:58:09 +0000 Subject: Fix clippy lint for identical `if`/`else` contraining `?` expressions Follow up to #114819. --- src/tools/clippy/clippy_utils/src/hir_utils.rs | 3 ++- src/tools/clippy/tests/ui/if_same_then_else2.rs | 2 +- src/tools/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 fdc35cd4ddf..98441e83eb4 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 c545434efe5..0b171f21d0c 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 37fe787d1de..56e5f3e45b2 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 -- cgit 1.4.1-3-g733a5 From 15beac89754f93a218b1075a8a92757b265d7b69 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 22 Aug 2023 17:59:58 -0700 Subject: 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 1833c2be108..50eecd007f6 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 1833c2be108aefcb5d25f6280cf9763b1feb8005 +Subproject commit 50eecd007f6bf135ad60493bc62102739038d59a -- cgit 1.4.1-3-g733a5 From 65217a72b08b21ae252794d0363796092e2219d7 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 11:44:18 +0900 Subject: 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 9f4e66d628b..ff81544ba91 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; -- cgit 1.4.1-3-g733a5 From aa7730003e01f6c7bd0fa6a7fea4dc9ea6aa63c5 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 22 Aug 2023 17:17:44 +0200 Subject: 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 + tests/ui/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 c4a7f717840..d7cb159149d 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 25982a45853..993c576d697 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 42ad4d61c8e..796966b22d5 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 c1589f13835..47b95460ec3 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 -- cgit 1.4.1-3-g733a5 From 03fd2d4379cc0f5d6a04dd1708c75d2f828f598e Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 23 Aug 2023 21:57:18 +0900 Subject: Allow MaybeUninit in input and output of inline assembly --- .../rustc_hir_analysis/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 945953edd5a..cd7e9917204 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 00000000000..d7e4a948954 --- /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 +} -- cgit 1.4.1-3-g733a5 From 735e9c0c510927c309005dfa5db32bb13a573bae Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Tue, 22 Aug 2023 00:15:38 -0400 Subject: 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 aea59c31379..1f3e7cb97d1 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 fe7fef5d0c1..79389f92a50 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, +} -- cgit 1.4.1-3-g733a5 From 7ab27c5ed5a3ed71056091f914ff84f98be1d753 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 15:53:48 +0200 Subject: 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 81fb13f4166..1ce7efdfc20 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 d7ff248a9bf..bb1c186668c 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 8220df5d4f3..92e06f3ab0f 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") + }), ] } -- cgit 1.4.1-3-g733a5 From d3f35e96c17de681f091b980eabff49bbd8652dd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 15:54:04 +0200 Subject: 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 00000000000..25615a73c3f --- /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() {} +} -- cgit 1.4.1-3-g733a5 From 73ccfc56832b1948f2656c867744be6438d5ac4b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Aug 2023 16:33:07 +0200 Subject: 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 b280698230d..de8ff0e5f89 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` -- cgit 1.4.1-3-g733a5 From 107cb5c9045f8fadab431e42c8ba2335004efe47 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Tue, 22 Aug 2023 01:09:10 -0400 Subject: 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 1f3e7cb97d1..392dbafcb3e 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 8e38e394b98..360f2195c1c 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 79389f92a50..5929823b1bb 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 { -- cgit 1.4.1-3-g733a5 From 9cabc91a5fa20d4656674b2fad59dc3880f90103 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Mon, 31 Jul 2023 17:39:51 +0200 Subject: 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 9b274cc277e..02b023fe75b 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 -- cgit 1.4.1-3-g733a5 From 1c5f1762b71c46d537c9cbfd3cc60f82b9175793 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 23 Aug 2023 16:00:42 +0000 Subject: Do not convert copies of packed projections to moves. --- .../src/dead_store_elimination.rs | 4 ++++ ...ve_packed.DeadStoreElimination.panic-abort.diff | 15 +++++++++++++ ...e_packed.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 3f988930b5e..47c1c465e56 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 00000000000..dc0f9073416 --- /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 00000000000..86ef026ec5c --- /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 41f91fc1306..f09cdee1482 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 }); } -- cgit 1.4.1-3-g733a5 From 6101ddd793daf8bea541073c2d9462e252e81cec Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 23 Aug 2023 19:50:24 +0200 Subject: 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 6f0e544a597..23c858498a1 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 } -- cgit 1.4.1-3-g733a5 From f3d81917fc546420cb9deadc22cbab30133abd79 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 5 Jan 2023 13:55:24 -0800 Subject: 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 e3d66d18388..db669ca7250 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 31b6961bb62..f8d40c4142d 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 a7ed74f4721..dc1e5967859 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 { -- cgit 1.4.1-3-g733a5 From 246a6a6589b118c0a08e449f981bb4ae07bc089a Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 23 Aug 2023 20:16:22 +0200 Subject: 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 37ec2f0801c..ab57d5c6803 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); } }); -- cgit 1.4.1-3-g733a5 From d4ab99d946590e5d62a0aafc0e8fd1d4605e4bc6 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 23 Aug 2023 11:47:35 -0700 Subject: 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 d48e6533a20..9bd04e11cb3 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 79b1551f301..592e97310a4 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 -- cgit 1.4.1-3-g733a5 From 912d11d4d1d36cb1c7a686b43a64b5f96dd58fe4 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 23 Aug 2023 11:52:49 -0700 Subject: 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 ++--- tests/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 77c0e82330f..dbe316f573d 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 48672f12da1..3b82561ec7d 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 0ab776c21ed..1a62eb2bae8 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 5f251b3b890..89c5d06c0b2 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 e5ee60fad59..4db65b61dc6 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 424c5dce273..4aca303e6dc 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 b4642874532..30817a42e8a 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; -- cgit 1.4.1-3-g733a5 From c1a7af0f2a691c2e74479156475018b497f3c288 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 23 Aug 2023 21:39:16 +0000 Subject: 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 d62541daf07..31e863b8a4e 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 00000000000..16512b8a3cd --- /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 00000000000..276edeccb22 --- /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 00000000000..77f991a9a61 --- /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`. -- cgit 1.4.1-3-g733a5 From 0a916062aac997071d020159bd6f12a57ca3fd2c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 22 Aug 2023 07:06:38 -0400 Subject: 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 12dd1542d79..7f2cab3eb11 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 e45b7c154fa..f14463fe940 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 ef2788efbcf..3f544bf7209 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 33772089744..bee5a89c4c7 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 3bf15505090..6c29144569d 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 34518b53759..db5df554d23 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 c4a9b2ace9a..8b1fc5b90b4 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 34214931a08..094d5b1e77c 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 9942c70c4ae..c3de446a66e 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 585b10e79e4..e578f09b58f 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 f4593d0fe73..85829906f4e 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 d3fc1b2850e..50b69181d67 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 892be36aae7..598adbe7985 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 53005ede843..775870106b1 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 76e54e60d14..410705952bf 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 a270817f310..d6c746a7bd8 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 c24b8d9ec17..efaed0f68ce 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 b52002b1239..e838e11131f 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 b0f8ea7a05d..e0abc7f04f5 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 efe8f5a8bcf..e43b6ac4039 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 183dd8e6e59..9cb27899f10 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 bf4c682d33e..4bbe61ca3e7 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 676d4f2f38c..605870b8a7b 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 ef0a2fd4ec4..b99346b6ba6 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 a2729b3743c..f39c4176440 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 76b35919658..02534491da9 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 009014de5c2..e7d34daa079 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 83d637b685a..d382fec9352 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 a81d0a63547..ac685b18c29 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 58684ffe500..1955ef815ff 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 64d10dd5712..413f0fba342 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 0b4daeafe46..62e97c65569 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 4ef79af3124..a2c828701e5 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); -- cgit 1.4.1-3-g733a5 From 81a24922e796445054b4cb32e2dd644c696787a2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 23 Aug 2023 23:53:37 +0100 Subject: 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 d7cb159149d..7f7f36ca170 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 aabefb729f3..9a0f3ca5118 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 68167487a1b..e63741820af 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 0a40d17f98e..f58782c0f22 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(), + 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(), - RenamedOrRemovedLint { msg, suggestion }, + 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 993c576d697..0e942d774a7 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 { -- cgit 1.4.1-3-g733a5 From 73152a3efb29807dffeb12456f5aedf79dfb308a Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 24 Aug 2023 00:23:01 +0100 Subject: 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 9a0f3ca5118..9dfde84b552 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 e63741820af..607875b3faa 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>, } -- cgit 1.4.1-3-g733a5 From 868706d9b50ddf27995a9ee4d863e163b78b7365 Mon Sep 17 00:00:00 2001 From: Frank King Date: Wed, 23 Aug 2023 20:53:47 +0800 Subject: 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 +++ compiler/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 ++ compiler/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 + src/tools/rustfmt/tests/target/anonymous-types.rs | 19 +++++ .../feature-gates/feature-gate-unnamed_fields.rs | 26 +++++++ .../feature-gate-unnamed_fields.stderr | 84 +++++++++++++++++++++ tests/ui/parser/keyword-union-as-identifier.rs | 72 ++++++++++++++++++ .../unnamed-fields/restrict_anonymous_structs.rs | 37 ++++++++++ .../restrict_anonymous_structs.stderr | 78 ++++++++++++++++++++ .../unnamed-fields/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 58725a08c7c..395540764ea 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 bae3979fbf9..55a1772adb1 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 f4ad0efa423..300b1486f9b 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 6d474de2d15..ddbbf5a10bc 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 0aeff22ca9f..79ed6b9b2aa 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 2f0ac0c2b19..429dc2c94a9 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 af594a00705..371ae7947ca 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 ab8015c4a43..d706cb170e8 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 c4efad7caf2..036c5311241 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 068b255e9f2..187c5bee843 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 d27a44f1206..3393f034bc3 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 898f5fd3b70..cde9dbd8e92 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 24c65d061f9..5db31c23478 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 3bb50b05aa3..fa81596cc96 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 5aa8aef6a85..24087a4eabb 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 745a3590720..539fc9da1a8 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 18a08f17ba0..5e8edd8f8bf 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 00000000000..8e08c314ed1 --- /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 00000000000..4bbd0c83bfb --- /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 00000000000..f026f2c3600 --- /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 00000000000..7062557d731 --- /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 00000000000..192bbba5a5b --- /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 00000000000..fd731766c01 --- /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 00000000000..c69266089bb --- /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 00000000000..c65cad775a9 --- /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 + -- cgit 1.4.1-3-g733a5 From ec2c95e0932312c994ee8c5d52b7ee93b5ae65b9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 23 Aug 2023 23:29:34 -0400 Subject: 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 588164e4a85..9dbc87c337c 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 bf8cb4bd768..17c308e915b 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" ); } } -- cgit 1.4.1-3-g733a5 From 9f1de6171c209ae20438827f42ffd625963adfc1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 24 Aug 2023 06:31:10 +0200 Subject: 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 7bbed0877f0..841c626d0a3 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 71f2591fe66..f76c69af526 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 } +} -- cgit 1.4.1-3-g733a5 From 9ce35198bfd7a02248037d6afe31a652293a1fdf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 6 Jul 2023 16:37:15 +0300 Subject: 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 3bd9cea27ce..669f7930064 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 76e54e60d14..c1bc2741571 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(), -- cgit 1.4.1-3-g733a5 From 2063067a8159d9527f98630af7d79397a358fcd3 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 24 Aug 2023 12:44:42 +0200 Subject: 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. --- .../ui/consts/const-eval/ub-int-array.32bit.stderr | 36 ---------------------- .../ui/consts/const-eval/ub-int-array.64bit.stderr | 36 ---------------------- tests/ui/consts/const-eval/ub-int-array.rs | 8 +++-- tests/ui/consts/const-eval/ub-int-array.stderr | 36 ++++++++++++++++++++++ 4 files changed, 42 insertions(+), 74 deletions(-) delete mode 100644 tests/ui/consts/const-eval/ub-int-array.32bit.stderr delete mode 100644 tests/ui/consts/const-eval/ub-int-array.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-int-array.stderr diff --git a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr b/tests/ui/consts/const-eval/ub-int-array.32bit.stderr deleted file mode 100644 index b3df41304ac..00000000000 --- a/tests/ui/consts/const-eval/ub-int-array.32bit.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.64bit.stderr b/tests/ui/consts/const-eval/ub-int-array.64bit.stderr deleted file mode 100644 index b3df41304ac..00000000000 --- 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 adcf376b9c7..cde0749dc5f 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.stderr b/tests/ui/consts/const-eval/ub-int-array.stderr new file mode 100644 index 00000000000..c8efd7e1bd3 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-int-array.stderr @@ -0,0 +1,36 @@ +error[E0080]: it is undefined behavior to use this value + --> $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) { + __ __ __ __ 11 11 11 11 22 22 22 22 │ ░░░░...."""" + } + +error[E0080]: it is undefined behavior to use this value + --> $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 + | + = 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:46: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`. -- cgit 1.4.1-3-g733a5 From 05010b60740ca03e5bd566d656ce2ddfc1ac5e3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 14:21:12 +0800 Subject: resolve: Make bindings from extern prelude unique instead of creating a new every time a name from extern prelude is accessed --- compiler/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 127bec22c17..476b5f733a6 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 c1bc2741571..2f104df02dc 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>` -- cgit 1.4.1-3-g733a5 From d1f8ea417c9276528f94766195337ef02fe39446 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 17:18:26 +0800 Subject: 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 669f7930064..21bc54ede4d 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 2f104df02dc..6c63abe47fb 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(), -- cgit 1.4.1-3-g733a5 From 02640f9d5985f87b4dccaf987e6c34d2b7a40fdd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Aug 2023 16:53:06 +0800 Subject: 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 21bc54ede4d..7412b2d0581 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 6c63abe47fb..a2ee6c7b529 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 { -- cgit 1.4.1-3-g733a5 From 50bbe01de0abe85d1a4c07a2f163e540c1508f0d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 22 Aug 2023 19:14:32 +0800 Subject: 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 cd1a9b934cf..d99fc07a7cd 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 7412b2d0581..2cf34ccb3ad 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 a2ee6c7b529..57d9232005b 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 6a5b675b4bb..1199290a4d1 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) { -- cgit 1.4.1-3-g733a5 From 453edebc703777dcfe39f8c1c7fa472d8ae7c70e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 23 Aug 2023 15:21:18 +0800 Subject: 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 2cf34ccb3ad..61e05b65f90 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 }; -- cgit 1.4.1-3-g733a5 From 4c53783f3c27ce30119018c752bdc805222409da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:57:10 +0200 Subject: 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 +- compiler/rustc_codegen_cranelift/src/constant.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 151 +++++++++++---------- compiler/rustc_codegen_ssa/src/mir/mod.rs | 8 +- .../rustc_const_eval/src/interpret/eval_context.rs | 5 +- compiler/rustc_const_eval/src/interpret/machine.rs | 11 +- .../rustc_const_eval/src/interpret/terminator.rs | 4 +- .../src/transform/check_consts/check.rs | 2 +- .../check_consts/post_drop_elaboration.rs | 2 +- .../rustc_const_eval/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 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 2 +- .../rustc_mir_dataflow/src/framework/direction.rs | 8 +- .../src/impls/borrowed_locals.rs | 2 +- .../src/impls/storage_liveness.rs | 4 +- .../rustc_mir_dataflow/src/move_paths/builder.rs | 2 +- compiler/rustc_mir_dataflow/src/value_analysis.rs | 2 +- .../src/abort_unwinding_calls.rs | 2 +- .../rustc_mir_transform/src/add_call_guards.rs | 6 +- compiler/rustc_mir_transform/src/check_unsafety.rs | 2 +- .../rustc_mir_transform/src/const_prop_lint.rs | 2 +- compiler/rustc_mir_transform/src/coverage/graph.rs | 2 +- compiler/rustc_mir_transform/src/coverage/spans.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- .../rustc_mir_transform/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 +- ..._panic_abort.main.AbortUnwindingCalls.after.mir | 2 +- .../basic_assignment.main.ElaborateDrops.diff | 6 +- ...c_assignment.main.SimplifyCfg-initial.after.mir | 6 +- ...expr.main.ElaborateDrops.before.panic-abort.mir | 6 +- ...xpr.main.ElaborateDrops.before.panic-unwind.mir | 6 +- .../building/enum_cast.droppy.built.after.mir | 2 +- ...y_move_out.move_out_by_subslice.built.after.mir | 6 +- ...rray_move_out.move_out_from_end.built.after.mir | 6 +- ...s.{impl#0}-clone.InstSimplify.panic-unwind.diff | 2 +- ...refer_inline_test.main.Derefer.panic-abort.diff | 2 +- ...efer_inline_test.main.Derefer.panic-unwind.diff | 2 +- ...osure#0}.StateTransform.before.panic-unwind.mir | 4 +- .../inline/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 +- ...generic_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 +- .../issue_78442.bar.Inline.panic-unwind.diff | 2 +- .../issue_78442.bar.RevealAll.panic-unwind.diff | 2 +- .../inline/unsized_argument.caller.Inline.diff | 2 +- ...ssue_41110.main.ElaborateDrops.panic-abort.diff | 8 +- ...sue_41110.main.ElaborateDrops.panic-unwind.diff | 8 +- ...ssue_41110.test.ElaborateDrops.panic-abort.diff | 10 +- ...sue_41110.test.ElaborateDrops.panic-unwind.diff | 10 +- ...ssue_41888.main.ElaborateDrops.panic-abort.diff | 6 +- ...sue_41888.main.ElaborateDrops.panic-unwind.diff | 6 +- ...2289.test.ElaborateDrops.before.panic-abort.mir | 4 +- ...289.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 +- ...lifyCfg-initial.after-ElaborateDrops.after.diff | 2 +- ...lifyCfg-initial.after-ElaborateDrops.after.diff | 2 +- ...call.main.ElaborateDrops.before.panic-abort.mir | 2 +- ...all.main.ElaborateDrops.before.panic-unwind.mir | 2 +- ...plifyCfg-elaborate-drops.after.panic-unwind.mir | 2 +- ...plifyCfg-elaborate-drops.after.panic-unwind.mir | 4 +- ...lace.[String].AddMovesForPackedDrops.before.mir | 2 +- ...lace.Vec_i32_.AddMovesForPackedDrops.before.mir | 2 +- 88 files changed, 383 insertions(+), 281 deletions(-) diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index d4c42a75874..84be50a6416 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 ef2788efbcf..ca96d14b89c 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 d91a3d94045..3004291c3e7 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 ed371a04c53..9159bc36987 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 7db5f79eead..a934b0767f1 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 3f5b46333d9..7fda2d5fadf 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] - // ... - - llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); - let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); - - let mut cs_bx = Bx::build(self.cx, llbb); - let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); - - // 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); + fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { + if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { + return bb; + } + + 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] + // ... + + llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); + let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); + + let mut cs_bx = Bx::build(self.cx, llbb); + let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); + + // 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 llpersonality = self.cx.eh_personality(); - bx.filter_landing_pad(llpersonality); + let llpersonality = self.cx.eh_personality(); + bx.filter_landing_pad(llpersonality); - funclet = None; - } + funclet = None; + } - self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); + self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); - let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item()); + let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); - bx.do_not_inline(llret); + let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + bx.do_not_inline(llret); - bx.unreachable(); + bx.unreachable(); - self.terminate_block = Some(llbb); - llbb - }) + 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 ccf93f208d5..7f38c54c36f 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 61d3de5c405..90848dbfbc7 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 d3c73b896c0..6be2e406917 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 b2ebcceceb3..ca7c484ea31 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 e67098a3ac3..f288ddc25d3 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 a8c61d2c8fd..fd6bc2ee9af 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 0dfbbf73dce..b829f24ab7a 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 302a9498413..23b20543d53 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 cd74a403ff6..419543b8988 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 e91e822f915..79b64a491f4 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 bd87563e2bb..c4d7f122ea9 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 b3d3366ae10..87b04aabe6a 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 567e7bfb5bf..4cf6a349af7 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 84c80bf41a4..94be38beee4 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 8a9e37c5a4f..70451edd500 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 5ed8f20b73f..3ad9d3d4264 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 531390c2f07..94d6eb67d49 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 4adf3dec61b..2e3b9577b50 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 1eea8eef0ad..6872ef5e985 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 5aed89139e2..4500bb7ff0f 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 fb4705e0754..b814fbf32b1 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 e72db1a59a0..0fce9cb19a8 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 4f8ca916d5b..da8913d604b 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 d3d4fcd3a52..60461691e7f 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 6fabaca524a..717763a94a0 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 a80ae480089..78d7ffb3698 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 96077322575..1e7161189c3 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 734e93783d1..9551c7a2a8d 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 5782adbb3ff..8c48a667786 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 de1b80585d1..e1e4acccccd 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 079cf9eb4e9..e1000d96932 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 cd7908e75e2..f917e52109a 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 aea59c31379..092d4932a6d 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 8aec12f128e..90dc6766cf2 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 7b6249207fe..d5e4c113018 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 43523faa236..17233058c9c 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 550c9650fb3..17cfcbb2018 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 25c9a7c44bc..9efba031250 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 a59ffe97bf0..8b9c853eb85 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 15269fb8f6c..2b6e0fe489a 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 a9bc2e89034..fac407ae1ea 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 d196b045a1b..f7cfcf27fe5 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 a72d22a9c9f..4cfdc8701c6 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 1caf9e4a523..d1f8b8daf74 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 fea1138ba8d..f7fc1eb7ce3 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 3def40a8578..95c061dc9fa 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 1a4372afe69..20f627a567d 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 024d9bc7f51..b59a377d27c 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 2ada087b4bd..effecc03738 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 6a4c5436fce..8ec9c46f95f 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 503dc5beb19..2371297aefb 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 684211b53b3..4c0be81ea26 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 f3a6ee22c20..6e95225a43d 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 ad801fd280a..cd3ea5ebd0e 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 99dc64115a9..66ce2f92186 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 ef85e075eeb..daabb0ffc21 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 5df730a9930..b3fee11e7dd 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 073ddeff7ca..e3f5e9810c6 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 b750330df92..9042121ea9f 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 7765e491d89..2a55b018f7c 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 6ee6a0ffe4c..0cddc5a36b1 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 11501907b88..4f7ca616792 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 11501907b88..4f7ca616792 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 65f4806aaf7..0f38e3961a6 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 4845fc732aa..8da15ec9e23 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 aca7fe95c18..562e684f29f 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 60ce9cd8ad9..c6cc80c09c0 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 ae0beffae18..151571f57eb 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 7ecdc428e59..bda3080edb9 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 92f52e138a5..6aa49aab20e 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 4529c58a137..2cf68321743 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 be09ed641b8..9452ba7e6bc 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 be09ed641b8..9452ba7e6bc 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 e22fc7d54bc..51a009056d7 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 6fb107929e6..95820cfafbc 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 bc04790028d..9a43756cbc0 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 508f964099a..09ff59ffa21 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 9bf69acd356..8d9f8985578 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 ee90a540720..3768d34dd8e 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: { -- cgit 1.4.1-3-g733a5 From ddea3f981ea16ef4bc1dec043c071dd99a5e411d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 12:25:15 +0200 Subject: 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 9ef3a1b30e4..6484c30167c 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 d5e4c113018..ab6aa0df428 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") } -- cgit 1.4.1-3-g733a5 From 114fde6ac74ffbaaca4d7241c3ee4e11303ae50d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 13:57:09 +0200 Subject: 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 0af587e8de8..6aef1664394 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 7f38c54c36f..37a209cec5e 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 419543b8988..da486c3465a 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 } -- cgit 1.4.1-3-g733a5 From af29a26378cdd90d663c5a93d671e70184772266 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 14:41:55 +0200 Subject: 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 66b378f62d6..95783945529 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 00000000000..b4519da4e6a --- /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 00000000000..fa201b9667f --- /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 00000000000..bb30398531f --- /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 00000000000..a6de98c4913 --- /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. -- cgit 1.4.1-3-g733a5 From 290ce462526872f4fee675a23011f6fa27960ff0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 13:31:43 +0200 Subject: bless more mir-opt tests by hand --- .../mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff | 2 +- tests/mir-opt/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 +- .../pre-codegen/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 54c33aac9e8..d017900fc4c 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 940b9ae1156..d7059d21488 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 2614160363e..9a10f5cb575 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 8eff46fb931..431661af705 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 4d7c017dad4..7cada9c148d 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 bbab4e47a3a..ef1f934c52b 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 836fa2677b1..b9636712f82 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 65baaf64a9e..0f323a56e61 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 f7b19e80e44..96160b272b9 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 43f8806e165..67d8442ab20 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): { -- cgit 1.4.1-3-g733a5 From e4c4f9b9d9dff15a8292c04057e538f3f3dbf797 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 13:46:37 +0200 Subject: 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 - .../mir-opt/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 f7879140f81..43030041983 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 dee43b0c6f8..23d78e98777 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 ecdb656cb85..e32e04384c4 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 67f549a511c..f3ba409229d 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 e5066c38b96..a139848bab2 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 cabd9419e92..9552144787d 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 68d78f74328..312565e45c3 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 fb3da68e4af..d4f28dda6c6 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 d80bff50c31..57ffb07e294 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 4e954aa3433..1790056369c 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 079ecccab28..a227c82d6a3 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 8c83df53dad..da805de451c 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 addedad1704..094503e1039 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 9abf35d63d3..0a2c2f4dec8 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" -- cgit 1.4.1-3-g733a5 From 6f8ae03f9b485c41a3c4fbc1f0d854b30b6e283a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 14:26:26 +0200 Subject: make MIR less verbose --- compiler/rustc_middle/src/mir/terminator.rs | 17 +++++++++++++---- ...nwind_panic_abort.main.AbortUnwindingCalls.after.mir | 2 +- tests/mir-opt/basic_assignment.main.ElaborateDrops.diff | 6 +++--- .../basic_assignment.main.SimplifyCfg-initial.after.mir | 6 +++--- .../box_expr.main.ElaborateDrops.before.panic-abort.mir | 6 +++--- ...box_expr.main.ElaborateDrops.before.panic-unwind.mir | 6 +++--- tests/mir-opt/building/enum_cast.droppy.built.after.mir | 2 +- ..._array_move_out.move_out_by_subslice.built.after.mir | 6 +++--- ...orm_array_move_out.move_out_from_end.built.after.mir | 6 +++--- ...itives.{impl#0}-clone.InstSimplify.panic-unwind.diff | 2 +- .../derefer_inline_test.main.Derefer.panic-abort.diff | 2 +- .../derefer_inline_test.main.Derefer.panic-unwind.diff | 2 +- ...n-{closure#0}.StateTransform.before.panic-unwind.mir | 4 ++-- .../inline/asm_unwind.main.Inline.panic-abort.diff | 2 +- .../inline/asm_unwind.main.Inline.panic-unwind.diff | 2 +- tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff | 2 +- tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff | 2 +- .../mir-opt/inline/cycle.main.Inline.panic-unwind.diff | 2 +- ...e_on_generic_rust_call.call.Inline.panic-unwind.diff | 2 +- .../inline/inline_box_fn.call.Inline.panic-unwind.diff | 2 +- .../inline/inline_diverging.h.Inline.panic-unwind.diff | 4 ++-- .../inline_into_box_place.main.Inline.panic-unwind.diff | 2 +- .../inline/issue_78442.bar.Inline.panic-unwind.diff | 2 +- .../inline/issue_78442.bar.RevealAll.panic-unwind.diff | 2 +- .../mir-opt/inline/unsized_argument.caller.Inline.diff | 2 +- .../issue_41110.main.ElaborateDrops.panic-abort.diff | 8 ++++---- .../issue_41110.main.ElaborateDrops.panic-unwind.diff | 8 ++++---- .../issue_41110.test.ElaborateDrops.panic-abort.diff | 10 +++++----- .../issue_41110.test.ElaborateDrops.panic-unwind.diff | 10 +++++----- .../issue_41888.main.ElaborateDrops.panic-abort.diff | 6 +++--- .../issue_41888.main.ElaborateDrops.panic-unwind.diff | 6 +++--- ...sue_62289.test.ElaborateDrops.before.panic-abort.mir | 4 ++-- ...ue_62289.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 +- ....SimplifyCfg-initial.after-ElaborateDrops.after.diff | 2 +- ....SimplifyCfg-initial.after-ElaborateDrops.after.diff | 2 +- ...fter_call.main.ElaborateDrops.before.panic-abort.mir | 2 +- ...ter_call.main.ElaborateDrops.before.panic-unwind.mir | 2 +- ...n.SimplifyCfg-elaborate-drops.after.panic-unwind.mir | 2 +- .../loops.filter_mapped.PreCodegen.after.mir | 2 +- .../pre-codegen/loops.mapped.PreCodegen.after.mir | 2 +- .../pre-codegen/loops.vec_move.PreCodegen.after.mir | 2 +- ..._iter.forward_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...ter.inclusive_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...er.enumerated_loop.PreCodegen.after.panic-unwind.mir | 2 +- ..._iter.forward_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...ce_iter.range_loop.PreCodegen.after.panic-unwind.mir | 2 +- ..._iter.reverse_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...n.SimplifyCfg-elaborate-drops.after.panic-unwind.mir | 4 ++-- ..._in_place.[String].AddMovesForPackedDrops.before.mir | 2 +- ..._in_place.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 c4d7f122ea9..7eddf13b3fb 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 8b9c853eb85..6c3128f8c36 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 2b6e0fe489a..f187f959727 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 fac407ae1ea..75070ffda11 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 f7cfcf27fe5..1c7ef7f8345 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 4cfdc8701c6..4ad1c2de129 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 d1f8b8daf74..ea0edb610f5 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 f7fc1eb7ce3..82424de0392 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 95c061dc9fa..0872d1b6ac0 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 20f627a567d..f2b87221f2b 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 b59a377d27c..8ac6acd0e4a 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 effecc03738..aa9fcb505e6 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 8ec9c46f95f..6fcceb6c66b 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 2371297aefb..aa9429c46d8 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 4c0be81ea26..ea9c360aa7b 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 6e95225a43d..b7fea4f2e14 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 cd3ea5ebd0e..1fd1014ba1d 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 66ce2f92186..e8299db47db 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 daabb0ffc21..b82961c2815 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 b3fee11e7dd..47fd0ed0799 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 e3f5e9810c6..9f8c5806c90 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 d017900fc4c..675292f06d6 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 9042121ea9f..5a946712ea4 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 2a55b018f7c..cbfb39115b3 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 0cddc5a36b1..ab81f707148 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 4f7ca616792..4469270a9b2 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 4f7ca616792..4469270a9b2 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 0f38e3961a6..78184f6aeeb 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 8da15ec9e23..688887c3c1f 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 562e684f29f..b57fe348c2d 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 c6cc80c09c0..2156850e38c 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 151571f57eb..73462967850 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 bda3080edb9..8264e2cabbc 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 6aa49aab20e..cce1a1fd2ef 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 2cf68321743..a66769f0d11 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 9452ba7e6bc..3e817ff433b 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 9452ba7e6bc..3e817ff433b 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 51a009056d7..99a7a6b6154 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 95820cfafbc..7364b329e12 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 9a43756cbc0..0ef19180459 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 d7059d21488..4db829a5ec3 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 9a10f5cb575..c30df7425d2 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 431661af705..cb29473d762 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 7cada9c148d..35f7356d47a 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 ef1f934c52b..a677e8b439f 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 b9636712f82..3d76bab7ce7 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 0f323a56e61..e8586cec981 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 96160b272b9..8bd072fd625 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 67d8442ab20..3cdc49f6056 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 09ff59ffa21..7d3346faba6 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 8d9f8985578..3a8b457a7a1 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 3768d34dd8e..b5879418355 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: { -- cgit 1.4.1-3-g733a5 From d5e79f2b8d84fa64eed0da6413874560b2552900 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 24 Aug 2023 06:43:52 +0200 Subject: 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 c4d3cbc9faa..f17f1d14bf3 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 61b9137eadd..97bd7789a63 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 8256c1f5f0f..60254dc475b 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. -- cgit 1.4.1-3-g733a5 From d3c3c17abb3a4cb38be0fec3ea2cb62bdd452e06 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 24 Aug 2023 09:41:30 +0100 Subject: Add more tests for if_let_guard --- tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs | 18 ++++++++ .../rfcs/rfc-2294-if-let-guard/exhaustive.stderr | 35 +++++++++++++++ .../rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs | 15 +++++++ .../rfc-2294-if-let-guard/guard-lifetime-1.stderr | 15 +++++++ .../rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs | 16 +++++++ .../rfc-2294-if-let-guard/guard-mutability-1.rs | 14 ++++++ .../guard-mutability-1.stderr | 11 +++++ .../rfc-2294-if-let-guard/guard-mutability-2.rs | 14 ++++++ .../guard-mutability-2.stderr | 11 +++++ .../rfcs/rfc-2294-if-let-guard/macro-expanded.rs | 16 +++++++ .../rfc-2294-if-let-guard/macro-expanded.stderr | 13 ++++++ tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs | 27 +++++++++++ tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr | 52 ++++++++++++++++++++++ .../partially-macro-expanded.rs | 18 ++++++++ tests/ui/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 00000000000..b4eb541398c --- /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 00000000000..ddd08854ff7 --- /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 00000000000..792225e656f --- /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 00000000000..b8e1bb324b1 --- /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 00000000000..aa2154e3e9e --- /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 00000000000..9353c9d92f8 --- /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 00000000000..009d153387e --- /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 00000000000..4efa02f57a6 --- /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 00000000000..07e7c6a2c07 --- /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 00000000000..423a2cd53fc --- /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 00000000000..41a20bf8ae1 --- /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 00000000000..9cb27c73b14 --- /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 00000000000..85df360daab --- /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 00000000000..d91b3a358da --- /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 00000000000..dba292ef9e2 --- /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; + } + _ => {} + } +} -- cgit 1.4.1-3-g733a5 From 15a68610dd06351feac543afcd0802e6e2622ac8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 24 Aug 2023 15:42:55 +0000 Subject: Only check packed ADT. --- compiler/rustc_const_eval/src/util/alignment.rs | 2 +- compiler/rustc_const_eval/src/util/mod.rs | 2 +- compiler/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 4f39dad205a..c1f0ff260d2 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 289e3422595..0aef7fa469e 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 47c1c465e56..ef14105041b 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)); } -- cgit 1.4.1-3-g733a5 From 339d636120cbec1a593557498389e616b47a032a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 18:22:32 +0200 Subject: 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 4ef79af3124..f8e5a158bfd 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 { -- cgit 1.4.1-3-g733a5 From c6ba5d9806565f6ddeb731df9eb3d218a51be4e8 Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 24 Aug 2023 13:30:53 -0300 Subject: 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 c0eff6dfd8f..40eadaaa820 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, -- cgit 1.4.1-3-g733a5 From 8216f17d7d09d1ac6224b99c0ebf719ed276e4a7 Mon Sep 17 00:00:00 2001 From: Olanti Date: Thu, 24 Aug 2023 02:05:32 +0300 Subject: Move issue 29181, 2804, 17431, 66768 --- src/tools/tidy/src/ui_tests.rs | 4 +- tests/ui/issue-2804.rs | 81 -------- tests/ui/issues/auxiliary/issue-29181.rs | 5 - tests/ui/issues/issue-17431-1.rs | 6 - tests/ui/issues/issue-17431-1.stderr | 14 -- tests/ui/issues/issue-17431-2.rs | 8 - tests/ui/issues/issue-17431-2.stderr | 20 -- tests/ui/issues/issue-17431-3.rs | 8 - tests/ui/issues/issue-17431-3.stderr | 14 -- tests/ui/issues/issue-17431-4.rs | 8 - tests/ui/issues/issue-17431-4.stderr | 14 -- tests/ui/issues/issue-17431-5.rs | 11 -- tests/ui/issues/issue-17431-5.stderr | 14 -- tests/ui/issues/issue-17431-6.rs | 8 - tests/ui/issues/issue-17431-6.stderr | 14 -- tests/ui/issues/issue-17431-7.rs | 6 - tests/ui/issues/issue-17431-7.stderr | 14 -- tests/ui/issues/issue-29181.rs | 9 - tests/ui/issues/issue-29181.stderr | 21 --- tests/ui/issues/issue-66768.rs | 205 --------------------- tests/ui/macros/issue-2804.rs | 81 ++++++++ tests/ui/structs-enums/enum-rec/issue-17431-6.rs | 8 + .../ui/structs-enums/enum-rec/issue-17431-6.stderr | 14 ++ tests/ui/structs-enums/enum-rec/issue-17431-7.rs | 6 + .../ui/structs-enums/enum-rec/issue-17431-7.stderr | 14 ++ tests/ui/structs-enums/struct-rec/issue-17431-1.rs | 6 + .../structs-enums/struct-rec/issue-17431-1.stderr | 14 ++ tests/ui/structs-enums/struct-rec/issue-17431-2.rs | 8 + .../structs-enums/struct-rec/issue-17431-2.stderr | 20 ++ tests/ui/structs-enums/struct-rec/issue-17431-3.rs | 8 + .../structs-enums/struct-rec/issue-17431-3.stderr | 14 ++ tests/ui/structs-enums/struct-rec/issue-17431-4.rs | 8 + .../structs-enums/struct-rec/issue-17431-4.stderr | 14 ++ tests/ui/structs-enums/struct-rec/issue-17431-5.rs | 11 ++ .../structs-enums/struct-rec/issue-17431-5.stderr | 14 ++ tests/ui/traits/issue-66768.rs | 205 +++++++++++++++++++++ tests/ui/typeck/auxiliary/issue-29181.rs | 5 + tests/ui/typeck/issue-29181.rs | 9 + tests/ui/typeck/issue-29181.stderr | 21 +++ 39 files changed, 482 insertions(+), 482 deletions(-) delete mode 100644 tests/ui/issue-2804.rs delete mode 100644 tests/ui/issues/auxiliary/issue-29181.rs delete mode 100644 tests/ui/issues/issue-17431-1.rs delete mode 100644 tests/ui/issues/issue-17431-1.stderr delete mode 100644 tests/ui/issues/issue-17431-2.rs delete mode 100644 tests/ui/issues/issue-17431-2.stderr delete mode 100644 tests/ui/issues/issue-17431-3.rs delete mode 100644 tests/ui/issues/issue-17431-3.stderr delete mode 100644 tests/ui/issues/issue-17431-4.rs delete mode 100644 tests/ui/issues/issue-17431-4.stderr delete mode 100644 tests/ui/issues/issue-17431-5.rs delete mode 100644 tests/ui/issues/issue-17431-5.stderr delete mode 100644 tests/ui/issues/issue-17431-6.rs delete mode 100644 tests/ui/issues/issue-17431-6.stderr delete mode 100644 tests/ui/issues/issue-17431-7.rs delete mode 100644 tests/ui/issues/issue-17431-7.stderr delete mode 100644 tests/ui/issues/issue-29181.rs delete mode 100644 tests/ui/issues/issue-29181.stderr delete mode 100644 tests/ui/issues/issue-66768.rs create mode 100644 tests/ui/macros/issue-2804.rs create mode 100644 tests/ui/structs-enums/enum-rec/issue-17431-6.rs create mode 100644 tests/ui/structs-enums/enum-rec/issue-17431-6.stderr create mode 100644 tests/ui/structs-enums/enum-rec/issue-17431-7.rs create mode 100644 tests/ui/structs-enums/enum-rec/issue-17431-7.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-1.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-1.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-2.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-2.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-3.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-3.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-4.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-4.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-5.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-17431-5.stderr create mode 100644 tests/ui/traits/issue-66768.rs create mode 100644 tests/ui/typeck/auxiliary/issue-29181.rs create mode 100644 tests/ui/typeck/issue-29181.rs create mode 100644 tests/ui/typeck/issue-29181.stderr diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3414924007b..6a197527a64 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/issue-2804.rs deleted file mode 100644 index 571028c5e40..00000000000 --- a/tests/ui/issue-2804.rs +++ /dev/null @@ -1,81 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - -use std::collections::{BTreeMap, HashMap}; -use std::option; - -#[derive(Clone, Debug)] -enum Json { - I64(i64), - U64(u64), - F64(f64), - String(String), - Boolean(bool), - Array(Array), - Object(Object), - Null, -} - -type Array = Vec; -type Object = BTreeMap; - -enum object { - bool_value(bool), - int_value(i64), -} - -fn lookup(table: Object, key: String, default: String) -> String -{ - match table.get(&key) { - option::Option::Some(&Json::String(ref s)) => { - s.to_string() - } - option::Option::Some(value) => { - println!("{} was expected to be a string but is a {:?}", key, value); - default - } - option::Option::None => { - default - } - } -} - -fn add_interface(_store: isize, managed_ip: String, data: Json) -> (String, object) -{ - match &data { - &Json::Object(ref interface) => { - let name = lookup(interface.clone(), - "ifDescr".to_string(), - "".to_string()); - let label = format!("{}-{}", managed_ip, name); - - (label, object::bool_value(false)) - } - _ => { - println!("Expected dict for {} interfaces, found {:?}", managed_ip, data); - ("gnos:missing-interface".to_string(), object::bool_value(true)) - } - } -} - -fn add_interfaces(store: isize, managed_ip: String, device: HashMap) --> Vec<(String, object)> { - match device["interfaces"] { - Json::Array(ref interfaces) => - { - interfaces.iter().map(|interface| { - add_interface(store, managed_ip.clone(), (*interface).clone()) - }).collect() - } - _ => - { - println!("Expected list for {} interfaces, found {:?}", managed_ip, - device["interfaces"]); - Vec::new() - } - } -} - -pub fn main() {} diff --git a/tests/ui/issues/auxiliary/issue-29181.rs b/tests/ui/issues/auxiliary/issue-29181.rs deleted file mode 100644 index bd1a9be4ef1..00000000000 --- a/tests/ui/issues/auxiliary/issue-29181.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![crate_type="lib"] - -pub mod foo { - pub use super::*; -} diff --git a/tests/ui/issues/issue-17431-1.rs b/tests/ui/issues/issue-17431-1.rs deleted file mode 100644 index 3b692cc0eeb..00000000000 --- a/tests/ui/issues/issue-17431-1.rs +++ /dev/null @@ -1,6 +0,0 @@ -struct Foo { foo: Option> } -//~^ ERROR recursive type `Foo` has infinite size - -impl Foo { fn bar(&self) {} } - -fn main() {} diff --git a/tests/ui/issues/issue-17431-1.stderr b/tests/ui/issues/issue-17431-1.stderr deleted file mode 100644 index e3af8976cee..00000000000 --- a/tests/ui/issues/issue-17431-1.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-1.rs:1:1 - | -LL | struct Foo { foo: Option> } - | ^^^^^^^^^^ --- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Foo { foo: Option>> } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-2.rs b/tests/ui/issues/issue-17431-2.rs deleted file mode 100644 index f7b9c6a55dd..00000000000 --- a/tests/ui/issues/issue-17431-2.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Baz { q: Option } -//~^ ERROR recursive types `Baz` and `Foo` have infinite size - -struct Foo { q: Option } - -impl Foo { fn bar(&self) {} } - -fn main() {} diff --git a/tests/ui/issues/issue-17431-2.stderr b/tests/ui/issues/issue-17431-2.stderr deleted file mode 100644 index 39a99ec1ef7..00000000000 --- a/tests/ui/issues/issue-17431-2.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0072]: recursive types `Baz` and `Foo` have infinite size - --> $DIR/issue-17431-2.rs:1:1 - | -LL | struct Baz { q: Option } - | ^^^^^^^^^^ --- recursive without indirection -... -LL | struct Foo { q: Option } - | ^^^^^^^^^^ --- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL ~ struct Baz { q: Option> } -LL | -LL | -LL ~ struct Foo { q: Option> } - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-3.rs b/tests/ui/issues/issue-17431-3.rs deleted file mode 100644 index 83a63a88b72..00000000000 --- a/tests/ui/issues/issue-17431-3.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::sync::Mutex; - -struct Foo { foo: Mutex> } -//~^ ERROR recursive type `Foo` has infinite size - -impl Foo { fn bar(&self) {} } - -fn main() {} diff --git a/tests/ui/issues/issue-17431-3.stderr b/tests/ui/issues/issue-17431-3.stderr deleted file mode 100644 index 394134c7855..00000000000 --- a/tests/ui/issues/issue-17431-3.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-3.rs:3:1 - | -LL | struct Foo { foo: Mutex> } - | ^^^^^^^^^^ --- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Foo { foo: Mutex>> } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-4.rs b/tests/ui/issues/issue-17431-4.rs deleted file mode 100644 index 48f0dba2aec..00000000000 --- a/tests/ui/issues/issue-17431-4.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::marker; - -struct Foo { foo: Option>>, marker: marker::PhantomData } -//~^ ERROR recursive type `Foo` has infinite size - -impl Foo { fn bar(&self) {} } - -fn main() {} diff --git a/tests/ui/issues/issue-17431-4.stderr b/tests/ui/issues/issue-17431-4.stderr deleted file mode 100644 index 3d141e44bab..00000000000 --- a/tests/ui/issues/issue-17431-4.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-4.rs:3:1 - | -LL | struct Foo { foo: Option>>, marker: marker::PhantomData } - | ^^^^^^^^^^^^^ ------ recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Foo { foo: Option>>>, marker: marker::PhantomData } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-5.rs b/tests/ui/issues/issue-17431-5.rs deleted file mode 100644 index 0fd6ee61156..00000000000 --- a/tests/ui/issues/issue-17431-5.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::marker; - -struct Foo { foo: Bar } - -struct Bar { x: Bar , marker: marker::PhantomData } -//~^ ERROR recursive type `Bar` has infinite size - -impl Foo { fn foo(&self) {} } - -fn main() { -} diff --git a/tests/ui/issues/issue-17431-5.stderr b/tests/ui/issues/issue-17431-5.stderr deleted file mode 100644 index 44a90a6fe38..00000000000 --- a/tests/ui/issues/issue-17431-5.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Bar` has infinite size - --> $DIR/issue-17431-5.rs:5:1 - | -LL | struct Bar { x: Bar , marker: marker::PhantomData } - | ^^^^^^^^^^^^^ -------- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Bar { x: Box> , marker: marker::PhantomData } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-6.rs b/tests/ui/issues/issue-17431-6.rs deleted file mode 100644 index b7e49873da8..00000000000 --- a/tests/ui/issues/issue-17431-6.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::sync::Mutex; - -enum Foo { X(Mutex>) } -//~^ ERROR recursive type `Foo` has infinite size - -impl Foo { fn bar(self) {} } - -fn main() {} diff --git a/tests/ui/issues/issue-17431-6.stderr b/tests/ui/issues/issue-17431-6.stderr deleted file mode 100644 index e0a8225507e..00000000000 --- a/tests/ui/issues/issue-17431-6.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-6.rs:3:1 - | -LL | enum Foo { X(Mutex>) } - | ^^^^^^^^ --- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | enum Foo { X(Mutex>>) } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-7.rs b/tests/ui/issues/issue-17431-7.rs deleted file mode 100644 index 4fd7862781b..00000000000 --- a/tests/ui/issues/issue-17431-7.rs +++ /dev/null @@ -1,6 +0,0 @@ -enum Foo { Voo(Option>) } -//~^ ERROR recursive type `Foo` has infinite size - -impl Foo { fn bar(&self) {} } - -fn main() { } diff --git a/tests/ui/issues/issue-17431-7.stderr b/tests/ui/issues/issue-17431-7.stderr deleted file mode 100644 index ecf072b8e8a..00000000000 --- a/tests/ui/issues/issue-17431-7.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-7.rs:1:1 - | -LL | enum Foo { Voo(Option>) } - | ^^^^^^^^ --- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | enum Foo { Voo(Option>>) } - | ++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-29181.rs b/tests/ui/issues/issue-29181.rs deleted file mode 100644 index 70e5bc01920..00000000000 --- a/tests/ui/issues/issue-29181.rs +++ /dev/null @@ -1,9 +0,0 @@ -// aux-build:issue-29181.rs - -extern crate issue_29181 as foo; - -fn main() { - 0.homura(); //~ ERROR no method named `homura` found - // Issue #47759, detect existing method on the fundamental impl: - let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type -} diff --git a/tests/ui/issues/issue-29181.stderr b/tests/ui/issues/issue-29181.stderr deleted file mode 100644 index 53addf2fe4d..00000000000 --- a/tests/ui/issues/issue-29181.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0599]: no method named `homura` found for type `{integer}` in the current scope - --> $DIR/issue-29181.rs:6:7 - | -LL | 0.homura(); - | ^^^^^^ method not found in `{integer}` - -error[E0689]: can't call method `exp` on ambiguous numeric type `{float}` - --> $DIR/issue-29181.rs:8:30 - | -LL | let _ = |x: f64| x * 2.0.exp(); - | ^^^ - | -help: you must specify a concrete type for this numeric value, like `f32` - | -LL | let _ = |x: f64| x * 2.0_f32.exp(); - | ~~~~~~~ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0599, E0689. -For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-66768.rs b/tests/ui/issues/issue-66768.rs deleted file mode 100644 index ce42c8b01cc..00000000000 --- a/tests/ui/issues/issue-66768.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Regression test for #66768. -// check-pass -#![allow(dead_code)] -//-^ "dead code" is needed to reproduce the issue. - -use std::marker::PhantomData; -use std::ops::{Add, Mul}; - -fn problematic_function(material_surface_element: Edge2dElement) -where - DefaultAllocator: FiniteElementAllocator, -{ - let _: Point2 = material_surface_element.map_reference_coords().into(); -} - -impl ArrayLength for UTerm { - type ArrayType = (); -} -impl> ArrayLength for UInt { - type ArrayType = GenericArrayImplEven; -} -impl> ArrayLength for UInt { - type ArrayType = GenericArrayImplOdd; -} -impl Add for UTerm { - type Output = U; - fn add(self, _: U) -> Self::Output { - unimplemented!() - } -} -impl Add> for UInt -where - Ul: Add, -{ - type Output = UInt, B1>; - fn add(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Mul for UTerm { - type Output = UTerm; - fn mul(self, _: U) -> Self { - unimplemented!() - } -} -impl Mul> for UInt -where - Ul: Mul>, -{ - type Output = UInt>, B0>; - fn mul(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Mul> for UInt -where - Ul: Mul>, - UInt>, B0>: Add>, -{ - type Output = Sum>, B0>, UInt>; - fn mul(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Allocator for DefaultAllocator -where - R: DimName, - C: DimName, - R::Value: Mul, - Prod: ArrayLength, -{ - type Buffer = ArrayStorage; - fn allocate_uninitialized(_: R, _: C) -> Self::Buffer { - unimplemented!() - } - fn allocate_from_iterator(_: R, _: C, _: I) -> Self::Buffer { - unimplemented!() - } -} -impl Allocator for DefaultAllocator { - type Buffer = VecStorage; - fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer { - unimplemented!() - } - fn allocate_from_iterator(_: Dynamic, _: C, _: I) -> Self::Buffer { - unimplemented!() - } -} -impl DimName for DimU1 { - type Value = U1; - fn name() -> Self { - unimplemented!() - } -} -impl DimName for DimU2 { - type Value = U2; - fn name() -> Self { - unimplemented!() - } -} -impl From> for Point -where - DefaultAllocator: Allocator, -{ - fn from(_: VectorN) -> Self { - unimplemented!() - } -} -impl FiniteElementAllocator for DefaultAllocator where - DefaultAllocator: Allocator + Allocator -{ -} -impl ReferenceFiniteElement for Edge2dElement { - type NodalDim = DimU1; -} -impl FiniteElement for Edge2dElement { - fn map_reference_coords(&self) -> Vector2 { - unimplemented!() - } -} - -type Owned = >::Buffer; -type MatrixMN = Matrix>; -type VectorN = MatrixMN; -type Vector2 = VectorN; -type Point2 = Point; -type U1 = UInt; -type U2 = UInt, B0>; -type Sum = >::Output; -type Prod = >::Output; - -struct GenericArray> { - _data: U::ArrayType, -} -struct GenericArrayImplEven { - _parent2: U, - _marker: T, -} -struct GenericArrayImplOdd { - _parent2: U, - _data: T, -} -struct B0; -struct B1; -struct UTerm; -struct UInt { - _marker: PhantomData<(U, B)>, -} -struct DefaultAllocator; -struct Dynamic; -struct DimU1; -struct DimU2; -struct Matrix { - _data: S, - _phantoms: PhantomData<(N, R, C)>, -} -struct ArrayStorage -where - R: DimName, - C: DimName, - R::Value: Mul, - Prod: ArrayLength, -{ - _data: GenericArray>, -} -struct VecStorage { - _data: N, - _nrows: R, - _ncols: C, -} -struct Point -where - DefaultAllocator: Allocator, -{ - _coords: VectorN, -} -struct Edge2dElement; - -trait ArrayLength { - type ArrayType; -} -trait Allocator { - type Buffer; - fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer; - fn allocate_from_iterator(nrows: R, ncols: C, iter: I) -> Self::Buffer; -} -trait DimName { - type Value; - fn name() -> Self; -} -trait FiniteElementAllocator: - Allocator + Allocator -{ -} -trait ReferenceFiniteElement { - type NodalDim; -} -trait FiniteElement: ReferenceFiniteElement -where - DefaultAllocator: FiniteElementAllocator, -{ - fn map_reference_coords(&self) -> VectorN; -} - -fn main() {} diff --git a/tests/ui/macros/issue-2804.rs b/tests/ui/macros/issue-2804.rs new file mode 100644 index 00000000000..571028c5e40 --- /dev/null +++ b/tests/ui/macros/issue-2804.rs @@ -0,0 +1,81 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use std::collections::{BTreeMap, HashMap}; +use std::option; + +#[derive(Clone, Debug)] +enum Json { + I64(i64), + U64(u64), + F64(f64), + String(String), + Boolean(bool), + Array(Array), + Object(Object), + Null, +} + +type Array = Vec; +type Object = BTreeMap; + +enum object { + bool_value(bool), + int_value(i64), +} + +fn lookup(table: Object, key: String, default: String) -> String +{ + match table.get(&key) { + option::Option::Some(&Json::String(ref s)) => { + s.to_string() + } + option::Option::Some(value) => { + println!("{} was expected to be a string but is a {:?}", key, value); + default + } + option::Option::None => { + default + } + } +} + +fn add_interface(_store: isize, managed_ip: String, data: Json) -> (String, object) +{ + match &data { + &Json::Object(ref interface) => { + let name = lookup(interface.clone(), + "ifDescr".to_string(), + "".to_string()); + let label = format!("{}-{}", managed_ip, name); + + (label, object::bool_value(false)) + } + _ => { + println!("Expected dict for {} interfaces, found {:?}", managed_ip, data); + ("gnos:missing-interface".to_string(), object::bool_value(true)) + } + } +} + +fn add_interfaces(store: isize, managed_ip: String, device: HashMap) +-> Vec<(String, object)> { + match device["interfaces"] { + Json::Array(ref interfaces) => + { + interfaces.iter().map(|interface| { + add_interface(store, managed_ip.clone(), (*interface).clone()) + }).collect() + } + _ => + { + println!("Expected list for {} interfaces, found {:?}", managed_ip, + device["interfaces"]); + Vec::new() + } + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs new file mode 100644 index 00000000000..b7e49873da8 --- /dev/null +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -0,0 +1,8 @@ +use std::sync::Mutex; + +enum Foo { X(Mutex>) } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(self) {} } + +fn main() {} diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr new file mode 100644 index 00000000000..e0a8225507e --- /dev/null +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-6.rs:3:1 + | +LL | enum Foo { X(Mutex>) } + | ^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum Foo { X(Mutex>>) } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-7.rs b/tests/ui/structs-enums/enum-rec/issue-17431-7.rs new file mode 100644 index 00000000000..4fd7862781b --- /dev/null +++ b/tests/ui/structs-enums/enum-rec/issue-17431-7.rs @@ -0,0 +1,6 @@ +enum Foo { Voo(Option>) } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() { } diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr new file mode 100644 index 00000000000..ecf072b8e8a --- /dev/null +++ b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-7.rs:1:1 + | +LL | enum Foo { Voo(Option>) } + | ^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum Foo { Voo(Option>>) } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-1.rs b/tests/ui/structs-enums/struct-rec/issue-17431-1.rs new file mode 100644 index 00000000000..3b692cc0eeb --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-1.rs @@ -0,0 +1,6 @@ +struct Foo { foo: Option> } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr new file mode 100644 index 00000000000..e3af8976cee --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-1.rs:1:1 + | +LL | struct Foo { foo: Option> } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Option>> } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-2.rs b/tests/ui/structs-enums/struct-rec/issue-17431-2.rs new file mode 100644 index 00000000000..f7b9c6a55dd --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.rs @@ -0,0 +1,8 @@ +struct Baz { q: Option } +//~^ ERROR recursive types `Baz` and `Foo` have infinite size + +struct Foo { q: Option } + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr new file mode 100644 index 00000000000..39a99ec1ef7 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr @@ -0,0 +1,20 @@ +error[E0072]: recursive types `Baz` and `Foo` have infinite size + --> $DIR/issue-17431-2.rs:1:1 + | +LL | struct Baz { q: Option } + | ^^^^^^^^^^ --- recursive without indirection +... +LL | struct Foo { q: Option } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct Baz { q: Option> } +LL | +LL | +LL ~ struct Foo { q: Option> } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-3.rs b/tests/ui/structs-enums/struct-rec/issue-17431-3.rs new file mode 100644 index 00000000000..83a63a88b72 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-3.rs @@ -0,0 +1,8 @@ +use std::sync::Mutex; + +struct Foo { foo: Mutex> } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr new file mode 100644 index 00000000000..394134c7855 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-3.rs:3:1 + | +LL | struct Foo { foo: Mutex> } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Mutex>> } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-4.rs b/tests/ui/structs-enums/struct-rec/issue-17431-4.rs new file mode 100644 index 00000000000..48f0dba2aec --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-4.rs @@ -0,0 +1,8 @@ +use std::marker; + +struct Foo { foo: Option>>, marker: marker::PhantomData } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr new file mode 100644 index 00000000000..3d141e44bab --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-4.rs:3:1 + | +LL | struct Foo { foo: Option>>, marker: marker::PhantomData } + | ^^^^^^^^^^^^^ ------ recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Option>>>, marker: marker::PhantomData } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-5.rs b/tests/ui/structs-enums/struct-rec/issue-17431-5.rs new file mode 100644 index 00000000000..0fd6ee61156 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-5.rs @@ -0,0 +1,11 @@ +use std::marker; + +struct Foo { foo: Bar } + +struct Bar { x: Bar , marker: marker::PhantomData } +//~^ ERROR recursive type `Bar` has infinite size + +impl Foo { fn foo(&self) {} } + +fn main() { +} diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr new file mode 100644 index 00000000000..44a90a6fe38 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Bar` has infinite size + --> $DIR/issue-17431-5.rs:5:1 + | +LL | struct Bar { x: Bar , marker: marker::PhantomData } + | ^^^^^^^^^^^^^ -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Bar { x: Box> , marker: marker::PhantomData } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/issue-66768.rs b/tests/ui/traits/issue-66768.rs new file mode 100644 index 00000000000..ce42c8b01cc --- /dev/null +++ b/tests/ui/traits/issue-66768.rs @@ -0,0 +1,205 @@ +// Regression test for #66768. +// check-pass +#![allow(dead_code)] +//-^ "dead code" is needed to reproduce the issue. + +use std::marker::PhantomData; +use std::ops::{Add, Mul}; + +fn problematic_function(material_surface_element: Edge2dElement) +where + DefaultAllocator: FiniteElementAllocator, +{ + let _: Point2 = material_surface_element.map_reference_coords().into(); +} + +impl ArrayLength for UTerm { + type ArrayType = (); +} +impl> ArrayLength for UInt { + type ArrayType = GenericArrayImplEven; +} +impl> ArrayLength for UInt { + type ArrayType = GenericArrayImplOdd; +} +impl Add for UTerm { + type Output = U; + fn add(self, _: U) -> Self::Output { + unimplemented!() + } +} +impl Add> for UInt +where + Ul: Add, +{ + type Output = UInt, B1>; + fn add(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Mul for UTerm { + type Output = UTerm; + fn mul(self, _: U) -> Self { + unimplemented!() + } +} +impl Mul> for UInt +where + Ul: Mul>, +{ + type Output = UInt>, B0>; + fn mul(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Mul> for UInt +where + Ul: Mul>, + UInt>, B0>: Add>, +{ + type Output = Sum>, B0>, UInt>; + fn mul(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Allocator for DefaultAllocator +where + R: DimName, + C: DimName, + R::Value: Mul, + Prod: ArrayLength, +{ + type Buffer = ArrayStorage; + fn allocate_uninitialized(_: R, _: C) -> Self::Buffer { + unimplemented!() + } + fn allocate_from_iterator(_: R, _: C, _: I) -> Self::Buffer { + unimplemented!() + } +} +impl Allocator for DefaultAllocator { + type Buffer = VecStorage; + fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer { + unimplemented!() + } + fn allocate_from_iterator(_: Dynamic, _: C, _: I) -> Self::Buffer { + unimplemented!() + } +} +impl DimName for DimU1 { + type Value = U1; + fn name() -> Self { + unimplemented!() + } +} +impl DimName for DimU2 { + type Value = U2; + fn name() -> Self { + unimplemented!() + } +} +impl From> for Point +where + DefaultAllocator: Allocator, +{ + fn from(_: VectorN) -> Self { + unimplemented!() + } +} +impl FiniteElementAllocator for DefaultAllocator where + DefaultAllocator: Allocator + Allocator +{ +} +impl ReferenceFiniteElement for Edge2dElement { + type NodalDim = DimU1; +} +impl FiniteElement for Edge2dElement { + fn map_reference_coords(&self) -> Vector2 { + unimplemented!() + } +} + +type Owned = >::Buffer; +type MatrixMN = Matrix>; +type VectorN = MatrixMN; +type Vector2 = VectorN; +type Point2 = Point; +type U1 = UInt; +type U2 = UInt, B0>; +type Sum = >::Output; +type Prod = >::Output; + +struct GenericArray> { + _data: U::ArrayType, +} +struct GenericArrayImplEven { + _parent2: U, + _marker: T, +} +struct GenericArrayImplOdd { + _parent2: U, + _data: T, +} +struct B0; +struct B1; +struct UTerm; +struct UInt { + _marker: PhantomData<(U, B)>, +} +struct DefaultAllocator; +struct Dynamic; +struct DimU1; +struct DimU2; +struct Matrix { + _data: S, + _phantoms: PhantomData<(N, R, C)>, +} +struct ArrayStorage +where + R: DimName, + C: DimName, + R::Value: Mul, + Prod: ArrayLength, +{ + _data: GenericArray>, +} +struct VecStorage { + _data: N, + _nrows: R, + _ncols: C, +} +struct Point +where + DefaultAllocator: Allocator, +{ + _coords: VectorN, +} +struct Edge2dElement; + +trait ArrayLength { + type ArrayType; +} +trait Allocator { + type Buffer; + fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer; + fn allocate_from_iterator(nrows: R, ncols: C, iter: I) -> Self::Buffer; +} +trait DimName { + type Value; + fn name() -> Self; +} +trait FiniteElementAllocator: + Allocator + Allocator +{ +} +trait ReferenceFiniteElement { + type NodalDim; +} +trait FiniteElement: ReferenceFiniteElement +where + DefaultAllocator: FiniteElementAllocator, +{ + fn map_reference_coords(&self) -> VectorN; +} + +fn main() {} diff --git a/tests/ui/typeck/auxiliary/issue-29181.rs b/tests/ui/typeck/auxiliary/issue-29181.rs new file mode 100644 index 00000000000..bd1a9be4ef1 --- /dev/null +++ b/tests/ui/typeck/auxiliary/issue-29181.rs @@ -0,0 +1,5 @@ +#![crate_type="lib"] + +pub mod foo { + pub use super::*; +} diff --git a/tests/ui/typeck/issue-29181.rs b/tests/ui/typeck/issue-29181.rs new file mode 100644 index 00000000000..70e5bc01920 --- /dev/null +++ b/tests/ui/typeck/issue-29181.rs @@ -0,0 +1,9 @@ +// aux-build:issue-29181.rs + +extern crate issue_29181 as foo; + +fn main() { + 0.homura(); //~ ERROR no method named `homura` found + // Issue #47759, detect existing method on the fundamental impl: + let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type +} diff --git a/tests/ui/typeck/issue-29181.stderr b/tests/ui/typeck/issue-29181.stderr new file mode 100644 index 00000000000..53addf2fe4d --- /dev/null +++ b/tests/ui/typeck/issue-29181.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `homura` found for type `{integer}` in the current scope + --> $DIR/issue-29181.rs:6:7 + | +LL | 0.homura(); + | ^^^^^^ method not found in `{integer}` + +error[E0689]: can't call method `exp` on ambiguous numeric type `{float}` + --> $DIR/issue-29181.rs:8:30 + | +LL | let _ = |x: f64| x * 2.0.exp(); + | ^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | let _ = |x: f64| x * 2.0_f32.exp(); + | ~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0689. +For more information about an error, try `rustc --explain E0599`. -- cgit 1.4.1-3-g733a5 From a8827eea27d6904976bb4f942edcf3c97da9a4b3 Mon Sep 17 00:00:00 2001 From: allaboutevemirolive Date: Thu, 24 Aug 2023 17:09:14 -0400 Subject: 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 db5df554d23..b7e1b0c8ad1 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'); } -- cgit 1.4.1-3-g733a5 From 5d6e2d70509fb521d7329ffa43de538ecf9b3af5 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Wed, 23 Aug 2023 16:02:25 -0700 Subject: 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 d345368d552..77457c8daaa 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 da608e180c5..2d8b13e2080 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"} -- cgit 1.4.1-3-g733a5 From df5a248cb1d557f8df9c9d0660e8d704bc1e0919 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Aug 2023 20:08:22 +0200 Subject: 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 b4519da4e6a..a1c797268d1 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 fa201b9667f..923bac69c50 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 bb30398531f..da2b24945be 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 a6de98c4913..3422f5ccc4d 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: -- cgit 1.4.1-3-g733a5 From cab9fc99c9394cf1ce74a19183362701e1608aa1 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 25 Aug 2023 09:25:57 +0300 Subject: 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 392dbafcb3e..e20f4845b4d 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 c16bd6cbd70..03e19a3349a 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, -- cgit 1.4.1-3-g733a5 From 9c3f44f922adaf1a5797c5e5e66414369ad5ffc8 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Wed, 23 Aug 2023 21:36:45 +0800 Subject: 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 56ab63be27d..b048b513592 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. -- cgit 1.4.1-3-g733a5 From 3dd1c6bc98c6c26f797527437b7f6195375bfcc6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 25 Aug 2023 09:42:57 -0300 Subject: 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 360f2195c1c..44938eaa035 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)) } -- cgit 1.4.1-3-g733a5 From ec21d584eee32b276b78c7115391218c799d5936 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 24 Aug 2023 15:36:40 -0400 Subject: Record allocation spans inside force_allocation --- compiler/rustc_const_eval/src/interpret/machine.rs | 11 ++++++++- compiler/rustc_const_eval/src/interpret/place.rs | 9 ++++---- src/tools/miri/src/machine.rs | 18 +++++++++++++++ .../fail/dangling_pointers/dangling_primitive.rs | 13 +++++++++++ .../dangling_pointers/dangling_primitive.stderr | 26 ++++++++++++++++++++++ .../deref-partially-dangling.stderr | 7 +++++- .../tests/fail/dangling_pointers/dyn_size.stderr | 7 +++++- .../fail/dangling_pointers/stack_temporary.stderr | 12 +++++++++- .../fail/intrinsics/out_of_bounds_ptr_1.stderr | 7 +++++- .../fail/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 d3c73b896c0..ff106fa4b1b 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 daadb758964..40a7a0f4e56 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 550c9650fb3..7b8cfe78f57 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 00000000000..393127341ca --- /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 00000000000..bdc9c31db40 --- /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 fe039ef3ada..92b1fcb1145 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 33aa6c84410..95a50bc8750 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 500f28a3cbc..4d2dfe28aed 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 4422310870a..e1102a6d216 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 1364e0f9009..99f28b3e4f8 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 -- cgit 1.4.1-3-g733a5 From 8ecdefb3db7e854561fd382ba19675c894f40170 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 25 Aug 2023 11:58:31 -0400 Subject: 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 ff106fa4b1b..2b8e8bfbdd9 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, -- cgit 1.4.1-3-g733a5 From 055452864e7fbb0cf15864160087d10030dc7260 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Aug 2023 18:07:00 +0000 Subject: Walk through full path in point_at_path_if_possible --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 52 ++++++++++++---------- tests/ui/const-generics/exhaustive-value.stderr | 4 +- .../generic-const-items/unsatisfied-bounds.stderr | 4 +- .../trait-bounds/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 c44d12e61e3..1861f141eed 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 4a26e09772d..0828f7896dc 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 1fda460372a..2cee53431a4 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 00000000000..91525bc90c4 --- /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 00000000000..32f6b00b20c --- /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 f3a4c689033..5a539884873 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 -- cgit 1.4.1-3-g733a5 From 13e8b13e15ec38da731a72513851aced2ee8fb24 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Aug 2023 18:28:34 +0000 Subject: 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 +-- .../ui/associated-types/substs-ppaux.normal.stderr | 4 +-- .../associated-types/substs-ppaux.verbose.stderr | 4 +-- .../dont-evaluate-array-len-on-err-1.stderr | 4 +-- tests/ui/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 +- tests/ui/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 1861f141eed..f6a5b8f97a1 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 86c62e7b7f1..0e0dec35b53 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 8bddcd95568..73365d64d56 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 acdc3be8c67..015b22f790f 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 ad67899e6da..484581b1028 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 d8eebeb0d21..cb51d9b1ea5 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 b8f6cb5ef97..fe9d0f6e6ed 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 8344b88c3be..713bc404f67 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 2d9c49af85a..452bf757df7 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 e8d0eec020f..c94563d3591 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 11f0c40160d..255878e1775 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 5e67b2c44f2..b04a7b7f2f1 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]` -- cgit 1.4.1-3-g733a5 From 1abaf40ec818dfc0a0ad50e6e772cce60acc8477 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 25 Aug 2023 17:54:50 -0400 Subject: 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 4094e378034..3c67bea7a22 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 34c0ce9dcf8..d6fce4ee78f 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 71d91f21362..e89843b5703 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 830c60d329e..fbc822d4eb6 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 9865a945bad..09d3f7638ca 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 547b4f3a984..d1877a8bcd2 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 923d27fd936..e7029174511 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 0bd2bc3b961..bdd64ab02b7 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 77ef086f29b..6d743903314 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 5cd9e57de19..5c379992b20 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 98517da1d0f..5cbb5cb65ba 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 bcc172b0fae..b609ad2472c 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::*; -- cgit 1.4.1-3-g733a5 From 72b721f48e3695f25a0935ad535e75e6777d829b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:24:56 +1000 Subject: 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 7e0139ae036..db17b557167 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 959d48ce9db..21f4e65de30 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 ae1cc1531ed..88c5dac65cb 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 16592d48dda..2107bb59c02 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 8b8e9d5483f..20882fd4df0 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 0e4365fc797..4cd40384780 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 e3e89e9c8b3..a90827572bb 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 5074d8b3c37..c4ee9f23f08 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 a1285df0ec6..3492712a6f9 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 074e6b9835a..224c01d9a8b 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 c160b3db03f..9f695b7fd11 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 0b5a2c03dd3..94c7967215c 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 4c6a8a9b703..ab7aee51d1b 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 c34dbde888a..73f6fbd0c2b 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 0bfbdda2cab..5b748aeefb7 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 ba25e34bf86..056ffeb021a 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 fb6113eb01c..d985af13547 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 558dfaa5cff..a8fa24ac6a7 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 9da096dbd50..2cee358665a 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 48493e2079c..7d909c78647 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; -- cgit 1.4.1-3-g733a5 From 4da38c31d21347fe7800c4263cb34a8c9e62d0fb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:32:33 +1000 Subject: 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 07f1e6b3ee5..5797784f411 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 251b0c291e9..4006d723ce0 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 2107bb59c02..c086ef21e1a 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 20882fd4df0..a6651dd8a5e 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 809cf1f4821..211ba4cbe98 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 eb3a1ebff88..7c42458ae1b 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 f97ab230387..48e76318b0a 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 6f626b4a65b..9d4c90a827e 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 2cee358665a..50d92102a10 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 7d909c78647..c510b6a6c68 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() { -- cgit 1.4.1-3-g733a5 From 8d91e71e9a015c864b29725ec9430c5db4325cf4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Aug 2023 11:43:10 +1000 Subject: 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 ------ .../run-coverage/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 3c6108e436a..8b997724c4a 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 d32a37e078e..85e6662a6ad 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 db17b557167..fcb0a3aed64 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 21f4e65de30..2884ff297af 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 2b21dee6ccf..9dc50dae25a 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 a6651dd8a5e..e8929de6b36 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 211ba4cbe98..930348dc431 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 7c42458ae1b..16a2c4e33bd 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 4cd40384780..018e3160e4f 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 a90827572bb..3d6bdb38a2a 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 4749c353a64..473335ff641 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 057599d1b47..fa7f2a116c2 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 c99b980a339..2c9439a93b1 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 a9b5d1d1e7f..7b062719c6b 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 2ff8f917ed7..09839183566 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 150ffb9db39..bf4c2d8d685 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 48e76318b0a..cbc910664d0 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 224c01d9a8b..15f225326a4 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 9f695b7fd11..da546cfeef8 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 148a22377f3..8cd6f1be3f7 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 7116ce47f4b..f3a343bcc1f 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 2d60316e215..cee076e88cd 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 7df8de6f3cd..bbb65c1b35d 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 fcdb7437d00..5d48cbd62f2 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 9eb1d2db218..557cbf22bfa 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 c510b6a6c68..cc0e01ffde1 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 97808447ab7..49d39d36603 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 1c83c8fc7a8..b2f0eee2cc0 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 383dd991500..90c2641a7d6 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 ff7616656ff..361275c9215 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(()) { -- cgit 1.4.1-3-g733a5 From 20479074f4a68b855310ad79022499d7c7e08ade Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:25:22 +0000 Subject: 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 d96e7040aaf..f0eb71c0017 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c40cfcf0494ff7506e753e750adb00eeea839f9c +9334ec93541fd6963a3bfa2d2d09e3e33ac93131 -- cgit 1.4.1-3-g733a5 From ec91a2361ba0de6aa90f92fe620d49ef84b177ef Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:34:03 +0000 Subject: 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 98f82ec9a0f..9d01a04bf4a 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(()) } } -- cgit 1.4.1-3-g733a5