From 1ba71abddd744ff8bfbbb100c64ec8cbc52df62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 11 Mar 2021 00:00:00 +0000 Subject: [PATCH 01/23] Inline Attribute::has_name --- compiler/rustc_ast/src/attr/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 1e224dbf833..40b0cefd83a 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -120,6 +120,7 @@ pub fn name_value_literal_span(&self) -> Option { } impl Attribute { + #[inline] pub fn has_name(&self, name: Symbol) -> bool { match self.kind { AttrKind::Normal(ref item, _) => item.path == name, From 49431909a6a8ccb915302d57c869e86d2a576af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 11 Mar 2021 00:00:00 +0000 Subject: [PATCH 02/23] Validate rustc_layout_scalar_valid_range_{start,end} attributes --- compiler/rustc_passes/src/check_attr.rs | 37 ++++++++++++++++++- ...invalid_rustc_layout_scalar_valid_range.rs | 23 ++++++++++++ ...lid_rustc_layout_scalar_valid_range.stderr | 31 ++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs create mode 100644 src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c7b266f18bf..ae8883754d6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_ast::{Attribute, LitKind, NestedMetaItem}; +use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem}; use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -87,6 +87,10 @@ fn check_attributes( self.check_export_name(hir_id, &attr, span, target) } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) { self.check_rustc_args_required_const(&attr, span, target, item) + } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_start) { + self.check_rustc_layout_scalar_valid_range(&attr, span, target) + } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_end) { + self.check_rustc_layout_scalar_valid_range(&attr, span, target) } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { @@ -807,6 +811,37 @@ fn check_rustc_args_required_const( } } + fn check_rustc_layout_scalar_valid_range( + &self, + attr: &Attribute, + span: &Span, + target: Target, + ) -> bool { + if target != Target::Struct { + self.tcx + .sess + .struct_span_err(attr.span, "attribute should be applied to a struct") + .span_label(*span, "not a struct") + .emit(); + return false; + } + + let list = match attr.meta_item_list() { + None => return false, + Some(it) => it, + }; + + if matches!(&list[..], &[NestedMetaItem::Literal(Lit { kind: LitKind::Int(..), .. })]) { + true + } else { + self.tcx + .sess + .struct_span_err(attr.span, "expected exactly one integer literal argument") + .emit(); + false + } + } + /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs new file mode 100644 index 00000000000..25fe4be660b --- /dev/null +++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs @@ -0,0 +1,23 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(u32::MAX)] //~ ERROR +pub struct A(u32); + +#[rustc_layout_scalar_valid_range_end(1, 2)] //~ ERROR +pub struct B(u8); + +#[rustc_layout_scalar_valid_range_end(a = "a")] //~ ERROR +pub struct C(i32); + +#[rustc_layout_scalar_valid_range_end(1)] //~ ERROR +enum E { + X = 1, + Y = 14, +} + +fn main() { + let _ = A(0); + let _ = B(0); + let _ = C(0); + let _ = E::X; +} diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr new file mode 100644 index 00000000000..7e95fedebdf --- /dev/null +++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr @@ -0,0 +1,31 @@ +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:3:1 + | +LL | #[rustc_layout_scalar_valid_range_start(u32::MAX)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:6:1 + | +LL | #[rustc_layout_scalar_valid_range_end(1, 2)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:9:1 + | +LL | #[rustc_layout_scalar_valid_range_end(a = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to a struct + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1 + | +LL | #[rustc_layout_scalar_valid_range_end(1)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / enum E { +LL | | X = 1, +LL | | Y = 14, +LL | | } + | |_- not a struct + +error: aborting due to 4 previous errors + From 9613a88db5fd8bf3a882be35a9e8e87075e41bea Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 13 Mar 2021 13:13:27 -0800 Subject: [PATCH 03/23] Refactor `check_doc_attrs` body This change makes it easier to follow the control flow. I also moved the end-of-line comments attached to some symbols to before the symbol listing. This allows rustfmt to format the code; otherwise no formatting occurs (see rust-lang/rustfmt#4750). --- compiler/rustc_passes/src/check_attr.rs | 77 +++++++++++++------------ 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c7b266f18bf..a045b0d596d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -531,60 +531,65 @@ fn check_attr_crate_level( } fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool { - if let Some(mi) = attr.meta() { - if let Some(list) = mi.meta_item_list() { - for meta in list { - if meta.has_name(sym::alias) { - if !self.check_attr_crate_level(meta, hir_id, "alias") - || !self.check_doc_alias(meta, hir_id, target) + if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) { + for meta in list { + if let Some(i_meta) = meta.meta_item() { + match i_meta.name_or_empty() { + sym::alias + if !self.check_attr_crate_level(&meta, hir_id, "alias") + || !self.check_doc_alias(&meta, hir_id, target) => { return false; } - } else if meta.has_name(sym::keyword) { - if !self.check_attr_crate_level(meta, hir_id, "keyword") - || !self.check_doc_keyword(meta, hir_id) + + sym::keyword + if !self.check_attr_crate_level(&meta, hir_id, "keyword") + || !self.check_doc_keyword(&meta, hir_id) => { return false; } - } else if meta.has_name(sym::test) { - if CRATE_HIR_ID != hir_id { + + sym::test if CRATE_HIR_ID != hir_id => { self.tcx.struct_span_lint_hir( INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| { lint.build( - "`#![doc(test(...)]` is only allowed as a crate level attribute" + "`#![doc(test(...)]` is only allowed \ + as a crate level attribute", ) .emit(); }, ); return false; } - } else if let Some(i_meta) = meta.meta_item() { - if ![ - sym::cfg, - sym::hidden, - sym::html_favicon_url, - sym::html_logo_url, - sym::html_no_source, - sym::html_playground_url, - sym::html_root_url, - sym::include, - sym::inline, - sym::issue_tracker_base_url, - sym::masked, - sym::no_default_passes, // deprecated - sym::no_inline, - sym::passes, // deprecated - sym::plugins, // removed, but rustdoc warns about it itself - sym::primitive, - sym::spotlight, - sym::test, - ] - .iter() - .any(|m| i_meta.has_name(*m)) - { + + // no_default_passes: deprecated + // passes: deprecated + // plugins: removed, but rustdoc warns about it itself + sym::alias + | sym::cfg + | sym::hidden + | sym::html_favicon_url + | sym::html_logo_url + | sym::html_no_source + | sym::html_playground_url + | sym::html_root_url + | sym::include + | sym::inline + | sym::issue_tracker_base_url + | sym::keyword + | sym::masked + | sym::no_default_passes + | sym::no_inline + | sym::passes + | sym::plugins + | sym::primitive + | sym::spotlight + | sym::test => {} + + _ => { self.tcx.struct_span_lint_hir( INVALID_DOC_ATTRIBUTES, hir_id, From 7189c05bf8fe5b9d21815c44540d76301c90a8aa Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 13 Mar 2021 13:25:27 -0800 Subject: [PATCH 04/23] Lint non-meta doc attributes E.g., `#[doc(123)]`. --- compiler/rustc_passes/src/check_attr.rs | 10 ++++++++++ src/test/ui/attributes/doc-attr.rs | 8 ++++++++ src/test/ui/attributes/doc-attr.stderr | 20 +++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a045b0d596d..5120edb2e35 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -605,6 +605,16 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo return false; } } + } else { + self.tcx.struct_span_lint_hir( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + |lint| { + lint.build(&format!("unknown `doc` attribute")).emit(); + }, + ); + return false; } } } diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs index 3a584112973..261ba75dfcb 100644 --- a/src/test/ui/attributes/doc-attr.rs +++ b/src/test/ui/attributes/doc-attr.rs @@ -8,3 +8,11 @@ //~^ ERROR unknown `doc` attribute //~^^ WARN pub fn foo() {} + +#[doc(123)] +//~^ ERROR unknown `doc` attribute +//~| WARN +#[doc("hello", "bar")] +//~^ ERROR unknown `doc` attribute +//~| WARN +fn bar() {} diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr index 21479d25fc2..6bff40a7f70 100644 --- a/src/test/ui/attributes/doc-attr.stderr +++ b/src/test/ui/attributes/doc-attr.stderr @@ -13,6 +13,24 @@ LL | #![deny(warnings)] = 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 #82730 +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:12:7 + | +LL | #[doc(123)] + | ^^^ + | + = 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 #82730 + +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:15:7 + | +LL | #[doc("hello", "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 #82730 + error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -22,5 +40,5 @@ LL | #![doc(as_ptr)] = 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 #82730 -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 7e972a39b8e9c7228ce230206326e3e4c4e81e2c Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 11 Mar 2021 15:41:51 -0800 Subject: [PATCH 05/23] Report error for each invalid nested attribute --- compiler/rustc_passes/src/check_attr.rs | 15 +++++++++------ src/test/ui/attributes/doc-attr.rs | 2 ++ src/test/ui/attributes/doc-attr.stderr | 11 ++++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5120edb2e35..a1871e796d8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -531,6 +531,8 @@ fn check_attr_crate_level( } fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool { + let mut is_valid = true; + if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) { for meta in list { if let Some(i_meta) = meta.meta_item() { @@ -539,14 +541,14 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo if !self.check_attr_crate_level(&meta, hir_id, "alias") || !self.check_doc_alias(&meta, hir_id, target) => { - return false; + is_valid = false } sym::keyword if !self.check_attr_crate_level(&meta, hir_id, "keyword") || !self.check_doc_keyword(&meta, hir_id) => { - return false; + is_valid = false } sym::test if CRATE_HIR_ID != hir_id => { @@ -562,7 +564,7 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo .emit(); }, ); - return false; + is_valid = false; } // no_default_passes: deprecated @@ -602,7 +604,7 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo .emit(); }, ); - return false; + is_valid = false; } } } else { @@ -614,11 +616,12 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo lint.build(&format!("unknown `doc` attribute")).emit(); }, ); - return false; + is_valid = false; } } } - true + + is_valid } /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid. diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs index 261ba75dfcb..1b037985a18 100644 --- a/src/test/ui/attributes/doc-attr.rs +++ b/src/test/ui/attributes/doc-attr.rs @@ -15,4 +15,6 @@ pub fn foo() {} #[doc("hello", "bar")] //~^ ERROR unknown `doc` attribute //~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN fn bar() {} diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr index 6bff40a7f70..51714d2da86 100644 --- a/src/test/ui/attributes/doc-attr.stderr +++ b/src/test/ui/attributes/doc-attr.stderr @@ -31,6 +31,15 @@ LL | #[doc("hello", "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 #82730 +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:15:16 + | +LL | #[doc("hello", "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 #82730 + error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -40,5 +49,5 @@ LL | #![doc(as_ptr)] = 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 #82730 -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From fe64970ed10230376b08c5d4187f9d204295383f Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 12 Mar 2021 12:27:52 -0800 Subject: [PATCH 06/23] Add another test case --- src/test/ui/attributes/doc-attr.rs | 5 +++++ src/test/ui/attributes/doc-attr.stderr | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs index 1b037985a18..daf73dd023c 100644 --- a/src/test/ui/attributes/doc-attr.rs +++ b/src/test/ui/attributes/doc-attr.rs @@ -17,4 +17,9 @@ pub fn foo() {} //~| WARN //~| ERROR unknown `doc` attribute //~| WARN +#[doc(foo::bar, crate::bar::baz = "bye")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN fn bar() {} diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr index 51714d2da86..a2831770943 100644 --- a/src/test/ui/attributes/doc-attr.stderr +++ b/src/test/ui/attributes/doc-attr.stderr @@ -40,6 +40,24 @@ LL | #[doc("hello", "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 #82730 +error: unknown `doc` attribute `` + --> $DIR/doc-attr.rs:20:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + | + = 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 #82730 + +error: unknown `doc` attribute `` + --> $DIR/doc-attr.rs:20:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #82730 + error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -49,5 +67,5 @@ LL | #![doc(as_ptr)] = 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 #82730 -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors From 5134047c4073de04749ddee31623318dbcaaffc1 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 13 Mar 2021 14:32:06 -0800 Subject: [PATCH 07/23] Add hyphen to "crate level" "crate level attribute" -> "crate-level attribute" --- compiler/rustc_passes/src/check_attr.rs | 4 ++-- src/test/rustdoc-ui/doc-alias-crate-level.stderr | 2 +- src/test/rustdoc-ui/doc-attr2.stderr | 4 ++-- src/test/ui/attributes/doc-attr2.stderr | 4 ++-- src/test/ui/rustdoc/doc-alias-crate-level.stderr | 2 +- src/test/ui/rustdoc/doc_keyword.stderr | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a1871e796d8..c89518df007 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -520,7 +520,7 @@ fn check_attr_crate_level( .struct_span_err( meta.span(), &format!( - "`#![doc({} = \"...\")]` isn't allowed as a crate level attribute", + "`#![doc({} = \"...\")]` isn't allowed as a crate-level attribute", attr_name, ), ) @@ -559,7 +559,7 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo |lint| { lint.build( "`#![doc(test(...)]` is only allowed \ - as a crate level attribute", + as a crate-level attribute", ) .emit(); }, diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr index 9e746cba05f..fc8095e03ca 100644 --- a/src/test/rustdoc-ui/doc-alias-crate-level.stderr +++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr @@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]` LL | #[doc(alias = "shouldn't work!")] | ^^^^^^^^^^^^^^^^^ -error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute +error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc-alias-crate-level.rs:1:8 | LL | #![doc(alias = "crate-level-not-working")] diff --git a/src/test/rustdoc-ui/doc-attr2.stderr b/src/test/rustdoc-ui/doc-attr2.stderr index eeb2c2be085..643107318b9 100644 --- a/src/test/rustdoc-ui/doc-attr2.stderr +++ b/src/test/rustdoc-ui/doc-attr2.stderr @@ -1,4 +1,4 @@ -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:4:7 | LL | #[doc(test(no_crate_inject))] @@ -13,7 +13,7 @@ LL | #![deny(warnings)] = 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 #82730 -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:9:12 | LL | #![doc(test(no_crate_inject))] diff --git a/src/test/ui/attributes/doc-attr2.stderr b/src/test/ui/attributes/doc-attr2.stderr index eeb2c2be085..643107318b9 100644 --- a/src/test/ui/attributes/doc-attr2.stderr +++ b/src/test/ui/attributes/doc-attr2.stderr @@ -1,4 +1,4 @@ -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:4:7 | LL | #[doc(test(no_crate_inject))] @@ -13,7 +13,7 @@ LL | #![deny(warnings)] = 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 #82730 -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:9:12 | LL | #![doc(test(no_crate_inject))] diff --git a/src/test/ui/rustdoc/doc-alias-crate-level.stderr b/src/test/ui/rustdoc/doc-alias-crate-level.stderr index c0467514ae1..bd32609ade2 100644 --- a/src/test/ui/rustdoc/doc-alias-crate-level.stderr +++ b/src/test/ui/rustdoc/doc-alias-crate-level.stderr @@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]` LL | #[doc(alias = "shouldn't work!")] | ^^^^^^^^^^^^^^^^^ -error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute +error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc-alias-crate-level.rs:5:8 | LL | #![doc(alias = "not working!")] diff --git a/src/test/ui/rustdoc/doc_keyword.stderr b/src/test/ui/rustdoc/doc_keyword.stderr index d72a876163e..0679bb8c5a7 100644 --- a/src/test/ui/rustdoc/doc_keyword.stderr +++ b/src/test/ui/rustdoc/doc_keyword.stderr @@ -10,7 +10,7 @@ error: `#[doc(keyword = "...")]` can only be used on modules LL | #[doc(keyword = "hall")] | ^^^^^^^^^^^^^^^^ -error: `#![doc(keyword = "...")]` isn't allowed as a crate level attribute +error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc_keyword.rs:4:8 | LL | #![doc(keyword = "hello")] From 13884dc2af3d993629eec4a5489dc99bd0a00a71 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 13 Mar 2021 16:36:38 -0800 Subject: [PATCH 08/23] Update `rustdoc-ui` versions of the `doc-attr` test It seems there are two copies of it: one in `src/test/ui/attributes/` and one in `src/test/rustdoc-ui/`. I'm guessing this is to test that the lint is emitted both when you run the compiler and when you run rustdoc. --- src/test/rustdoc-ui/doc-attr.rs | 15 +++++++++ src/test/rustdoc-ui/doc-attr.stderr | 47 ++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-ui/doc-attr.rs b/src/test/rustdoc-ui/doc-attr.rs index 3a584112973..daf73dd023c 100644 --- a/src/test/rustdoc-ui/doc-attr.rs +++ b/src/test/rustdoc-ui/doc-attr.rs @@ -8,3 +8,18 @@ //~^ ERROR unknown `doc` attribute //~^^ WARN pub fn foo() {} + +#[doc(123)] +//~^ ERROR unknown `doc` attribute +//~| WARN +#[doc("hello", "bar")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN +#[doc(foo::bar, crate::bar::baz = "bye")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN +fn bar() {} diff --git a/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr index 21479d25fc2..a2831770943 100644 --- a/src/test/rustdoc-ui/doc-attr.stderr +++ b/src/test/rustdoc-ui/doc-attr.stderr @@ -13,6 +13,51 @@ LL | #![deny(warnings)] = 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 #82730 +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:12:7 + | +LL | #[doc(123)] + | ^^^ + | + = 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 #82730 + +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:15:7 + | +LL | #[doc("hello", "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 #82730 + +error: unknown `doc` attribute + --> $DIR/doc-attr.rs:15:16 + | +LL | #[doc("hello", "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 #82730 + +error: unknown `doc` attribute `` + --> $DIR/doc-attr.rs:20:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + | + = 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 #82730 + +error: unknown `doc` attribute `` + --> $DIR/doc-attr.rs:20:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #82730 + error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -22,5 +67,5 @@ LL | #![doc(as_ptr)] = 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 #82730 -error: aborting due to 2 previous errors +error: aborting due to 7 previous errors From e161a2fd730624e79a7ed420dad7278d6589f6db Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 14 Mar 2021 01:37:13 -0500 Subject: [PATCH 09/23] Remove unused `opt_local_def_id_to_hir_id` function Found while investigating #82933 - all LocalDefIds are expected to have HirIds, there's no point in pretending otherwise. --- compiler/rustc_hir/src/definitions.rs | 5 ----- compiler/rustc_middle/src/hir/map/mod.rs | 5 ----- 2 files changed, 10 deletions(-) diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index ac6a359ee57..3266dfac702 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -342,11 +342,6 @@ pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId { self.def_id_to_hir_id[id].unwrap() } - #[inline] - pub fn opt_local_def_id_to_hir_id(&self, id: LocalDefId) -> Option { - self.def_id_to_hir_id[id] - } - #[inline] pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option { self.hir_id_to_def_id.get(&hir_id).copied() diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 41ecffb9c56..9d00f0715a0 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -180,11 +180,6 @@ pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { self.tcx.definitions.local_def_id_to_hir_id(def_id) } - #[inline] - pub fn opt_local_def_id_to_hir_id(&self, def_id: LocalDefId) -> Option { - self.tcx.definitions.opt_local_def_id_to_hir_id(def_id) - } - pub fn iter_local_def_id(&self) -> impl Iterator + '_ { self.tcx.definitions.iter_local_def_id() } From 71a784d763f78d91ac88e34a72405dfbba17f336 Mon Sep 17 00:00:00 2001 From: Motoki Ikeda Date: Sat, 13 Mar 2021 00:51:26 +0900 Subject: [PATCH 10/23] Fix a typo in `swap_nonoverlapping_bytes` --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 5026c48bdf4..5ac260fc883 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -512,7 +512,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { let t = t.as_mut_ptr() as *mut u8; // SAFETY: As `i < len`, and as the caller must guarantee that `x` and `y` are valid - // for `len` bytes, `x + i` and `y + i` must be valid adresses, which fulfills the + // for `len` bytes, `x + i` and `y + i` must be valid addresses, which fulfills the // safety contract for `add`. // // Also, the caller must guarantee that `x` and `y` are valid for writes, properly aligned, From 5ec0540da506fa9d3c0ca2aa3cca65055752e500 Mon Sep 17 00:00:00 2001 From: Motoki Ikeda Date: Sun, 14 Mar 2021 16:39:29 +0900 Subject: [PATCH 11/23] Fix a typo in thread_local_dtor.rs --- library/std/src/sys_common/thread_local_dtor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs index 6f5ebf4a271..f9971fb6f21 100644 --- a/library/std/src/sys_common/thread_local_dtor.rs +++ b/library/std/src/sys_common/thread_local_dtor.rs @@ -1,6 +1,6 @@ //! Thread-local destructor //! -//! Besides thread-local "keys" (pointer-sized non-adressable thread-local store +//! Besides thread-local "keys" (pointer-sized non-addressable thread-local store //! with an associated destructor), many platforms also provide thread-local //! destructors that are not associated with any particular data. These are //! often more efficient. From 6ddd840f36a3951fb1ef9c7649fab161500c8268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sun, 14 Mar 2021 16:00:02 +0300 Subject: [PATCH 12/23] Minor refactoring in try_index_step Merges `if-let` and `if x.is_some() { ... }` blocks --- compiler/rustc_typeck/src/check/place_op.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 254e41706f9..5bd385107ca 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -103,9 +103,9 @@ fn try_index_step( let method = self.try_overloaded_place_op(expr.span, self_ty, &[input_ty], PlaceOp::Index); - let result = method.map(|ok| { + if let Some(result) = method { debug!("try_index_step: success, using overloaded indexing"); - let method = self.register_infer_ok_obligations(ok); + let method = self.register_infer_ok_obligations(result); let mut adjustments = self.adjust_steps(autoderef); if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() { @@ -128,10 +128,8 @@ fn try_index_step( self.apply_adjustments(base_expr, adjustments); self.write_method_call(expr.hir_id, method); - (input_ty, self.make_overloaded_place_return_type(method).ty) - }); - if result.is_some() { - return result; + + return Some((input_ty, self.make_overloaded_place_return_type(method).ty)); } } From 14038c7df25d38b2f5b6790604374e1a33a01fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sun, 14 Mar 2021 17:06:18 +0300 Subject: [PATCH 13/23] Remove duplicate asserts, replace eq assert with assert_eq --- compiler/rustc_mir_build/src/build/expr/into.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 47f75825fb6..a2adbdddc40 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -427,7 +427,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => { - debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); + debug_assert_eq!(Category::of(&expr.kind), Some(Category::Place)); // Create a "fake" temporary variable so that we check that the // value is Sized. Usually, this is caught in type checking, but @@ -436,8 +436,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.local_decls.push(LocalDecl::new(expr.ty, expr.span)); } - debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); - let place = unpack!(block = this.as_place(block, expr)); let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg.push_assign(block, source_info, destination, rvalue); From 13076f90d2febedd44d395561b0ec844cac64f8b Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 14 Mar 2021 14:00:02 -0700 Subject: [PATCH 14/23] Tweak diagnostics - Tweak lint message - Display multi-segment paths correctly --- compiler/rustc_passes/src/check_attr.rs | 15 +++++++++------ src/test/rustdoc-ui/doc-attr.rs | 6 +++--- src/test/rustdoc-ui/doc-attr.stderr | 10 +++++----- src/test/ui/attributes/doc-attr.rs | 6 +++--- src/test/ui/attributes/doc-attr.stderr | 10 +++++----- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c89518df007..2edc2315f05 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -597,11 +597,14 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo hir_id, i_meta.span, |lint| { - lint.build(&format!( - "unknown `doc` attribute `{}`", - i_meta.name_or_empty() - )) - .emit(); + let msg = if let Ok(snippet) = + self.tcx.sess.source_map().span_to_snippet(i_meta.path.span) + { + format!("unknown `doc` attribute `{}`", snippet,) + } else { + String::from("unknown `doc` attribute") + }; + lint.build(&msg).emit(); }, ); is_valid = false; @@ -613,7 +616,7 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo hir_id, meta.span(), |lint| { - lint.build(&format!("unknown `doc` attribute")).emit(); + lint.build(&format!("invalid `doc` attribute")).emit(); }, ); is_valid = false; diff --git a/src/test/rustdoc-ui/doc-attr.rs b/src/test/rustdoc-ui/doc-attr.rs index daf73dd023c..980d1c0e207 100644 --- a/src/test/rustdoc-ui/doc-attr.rs +++ b/src/test/rustdoc-ui/doc-attr.rs @@ -10,12 +10,12 @@ pub fn foo() {} #[doc(123)] -//~^ ERROR unknown `doc` attribute +//~^ ERROR invalid `doc` attribute //~| WARN #[doc("hello", "bar")] -//~^ ERROR unknown `doc` attribute +//~^ ERROR invalid `doc` attribute //~| WARN -//~| ERROR unknown `doc` attribute +//~| ERROR invalid `doc` attribute //~| WARN #[doc(foo::bar, crate::bar::baz = "bye")] //~^ ERROR unknown `doc` attribute diff --git a/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr index a2831770943..cc2494c92e6 100644 --- a/src/test/rustdoc-ui/doc-attr.stderr +++ b/src/test/rustdoc-ui/doc-attr.stderr @@ -13,7 +13,7 @@ LL | #![deny(warnings)] = 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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:12:7 | LL | #[doc(123)] @@ -22,7 +22,7 @@ LL | #[doc(123)] = 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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:15:7 | LL | #[doc("hello", "bar")] @@ -31,7 +31,7 @@ LL | #[doc("hello", "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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:15:16 | LL | #[doc("hello", "bar")] @@ -40,7 +40,7 @@ LL | #[doc("hello", "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 #82730 -error: unknown `doc` attribute `` +error: unknown `doc` attribute `foo::bar` --> $DIR/doc-attr.rs:20:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] @@ -49,7 +49,7 @@ LL | #[doc(foo::bar, crate::bar::baz = "bye")] = 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 #82730 -error: unknown `doc` attribute `` +error: unknown `doc` attribute `crate::bar::baz` --> $DIR/doc-attr.rs:20:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs index daf73dd023c..980d1c0e207 100644 --- a/src/test/ui/attributes/doc-attr.rs +++ b/src/test/ui/attributes/doc-attr.rs @@ -10,12 +10,12 @@ pub fn foo() {} #[doc(123)] -//~^ ERROR unknown `doc` attribute +//~^ ERROR invalid `doc` attribute //~| WARN #[doc("hello", "bar")] -//~^ ERROR unknown `doc` attribute +//~^ ERROR invalid `doc` attribute //~| WARN -//~| ERROR unknown `doc` attribute +//~| ERROR invalid `doc` attribute //~| WARN #[doc(foo::bar, crate::bar::baz = "bye")] //~^ ERROR unknown `doc` attribute diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr index a2831770943..cc2494c92e6 100644 --- a/src/test/ui/attributes/doc-attr.stderr +++ b/src/test/ui/attributes/doc-attr.stderr @@ -13,7 +13,7 @@ LL | #![deny(warnings)] = 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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:12:7 | LL | #[doc(123)] @@ -22,7 +22,7 @@ LL | #[doc(123)] = 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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:15:7 | LL | #[doc("hello", "bar")] @@ -31,7 +31,7 @@ LL | #[doc("hello", "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 #82730 -error: unknown `doc` attribute +error: invalid `doc` attribute --> $DIR/doc-attr.rs:15:16 | LL | #[doc("hello", "bar")] @@ -40,7 +40,7 @@ LL | #[doc("hello", "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 #82730 -error: unknown `doc` attribute `` +error: unknown `doc` attribute `foo::bar` --> $DIR/doc-attr.rs:20:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] @@ -49,7 +49,7 @@ LL | #[doc(foo::bar, crate::bar::baz = "bye")] = 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 #82730 -error: unknown `doc` attribute `` +error: unknown `doc` attribute `crate::bar::baz` --> $DIR/doc-attr.rs:20:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] From 8f40e1180f65bdf7e88baa4bcc03d24baded9fca Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 14 Mar 2021 14:39:13 -0700 Subject: [PATCH 15/23] Use pretty-printer instead of `span_to_snippet` --- Cargo.lock | 1 + compiler/rustc_passes/Cargo.toml | 1 + compiler/rustc_passes/src/check_attr.rs | 11 ++++------- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25039b5cbd9..ceb3bdc6b22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4268,6 +4268,7 @@ name = "rustc_passes" version = "0.0.0" dependencies = [ "rustc_ast", + "rustc_ast_pretty", "rustc_attr", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index c87799f1c2a..4069fb2127e 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -19,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_lexer = { path = "../rustc_lexer" } +rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2edc2315f05..98771c91958 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -597,13 +597,10 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo hir_id, i_meta.span, |lint| { - let msg = if let Ok(snippet) = - self.tcx.sess.source_map().span_to_snippet(i_meta.path.span) - { - format!("unknown `doc` attribute `{}`", snippet,) - } else { - String::from("unknown `doc` attribute") - }; + let msg = format!( + "unknown `doc` attribute `{}`", + rustc_ast_pretty::pprust::path_to_string(&i_meta.path), + ); lint.build(&msg).emit(); }, ); From 7429c688a5988d1f7f836f870b8689c44fa3c9de Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 14 Mar 2021 19:03:16 -0400 Subject: [PATCH 16/23] Don't encode file information for span with a dummy location Fixes #83112 The location information for a dummy span isn't real, so don't encode it. This brings the incr comp cache code into line with the Span `StableHash` impl, which doesn't hash the location information for dummy spans. Previously, we would attempt to load the 'original' file from a dummy span - if the file id changed (e.g. due to being moved on disk), we would get an ICE, since the Span was still valid due to its hash being unchanged. --- .../src/ty/query/on_disk_cache.rs | 6 ++--- .../issue-83112-incr-test-moved-file/Makefile | 25 +++++++++++++++++++ .../issue-83112-incr-test-moved-file/main.rs | 1 + 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make/issue-83112-incr-test-moved-file/Makefile create mode 100644 src/test/run-make/issue-83112-incr-test-moved-file/main.rs diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index d0cd8a48f99..78193acc74a 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -1045,12 +1045,12 @@ impl<'a, 'tcx, E> Encodable> for Span E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - if *self == DUMMY_SP { + let span_data = self.data(); + if self.is_dummy() { TAG_PARTIAL_SPAN.encode(s)?; - return SyntaxContext::root().encode(s); + return span_data.ctxt.encode(s); } - let span_data = self.data(); let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo); let partial_span = match &pos { Some((file_lo, _, _)) => !file_lo.contains(span_data.hi), diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile new file mode 100644 index 00000000000..76ecaba0f6a --- /dev/null +++ b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile @@ -0,0 +1,25 @@ +include ../../run-make-fulldeps/tools.mk + +# FIXME https://github.com/rust-lang/rust/issues/78911 +# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64) + +# Regression test for issue #83112 +# The generated test harness code contains spans with a dummy location, +# but a non-dummy SyntaxContext. Previously, the incremental cache was encoding +# these spans as a full span (with a source file index), instead of skipping +# the encoding of the location information. If the file gest moved, the hash +# of the span will be unchanged (since it has a dummy location), so the incr +# cache would end up try to load a non-existent file using the previously +# enccoded source file id. + +SRC=$(TMPDIR)/src +INCR=$(TMPDIR)/incr + +all: + mkdir $(SRC) + mkdir $(SRC)/mydir + mkdir $(INCR) + cp main.rs $(SRC)/main.rs + $(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs + mv $(SRC)/main.rs $(SRC)/mydir/main.rs + $(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/main.rs b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs @@ -0,0 +1 @@ +fn main() {} From f190bc4f4736ae0aed9580a2b4ed16bc2d678d11 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 14 Mar 2021 16:55:59 -0400 Subject: [PATCH 17/23] Introduce `proc_macro_back_compat` lint, and emit for `time-macros-impl` Now that future-incompat-report support has landed in nightly Cargo, we can start to make progress towards removing the various proc-macro back-compat hacks that have accumulated in the compiler. This PR introduces a new lint `proc_macro_back_compat`, which results in a future-incompat-report entry being generated. All proc-macro back-compat warnings will be grouped under this lint. Note that this lint will never actually become a hard error - instead, we will remove the special cases for various macros, which will cause older versions of those crates to emit some other error. I've added code to fire this lint for the `time-macros-impl` case. This is the easiest case out of all of our current back-compat hacks - the crate was renamed to `time-macros`, so seeing a filename with `time-macros-impl` guarantees that an older version of the parent `time` crate is in use. When Cargo's future-incompat-report feature gets stabilized, affected users will start to see future-incompat warnings when they build their crates. --- compiler/rustc_ast/src/token.rs | 50 +------------ .../rustc_expand/src/proc_macro_server.rs | 70 +++++++++++++++++-- compiler/rustc_lint/src/context.rs | 3 + compiler/rustc_lint_defs/src/builtin.rs | 53 +++++++++++++- compiler/rustc_lint_defs/src/lib.rs | 1 + .../group-compat-hack/group-compat-hack.rs | 6 +- .../group-compat-hack.stderr | 70 +++++++++++++++++++ .../group-compat-hack.stdout | 18 ++--- 8 files changed, 206 insertions(+), 65 deletions(-) create mode 100644 src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 71792acb37d..093f7f2668c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -11,11 +11,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_macros::HashStable_Generic; -use rustc_span::hygiene::ExpnKind; -use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP}; +use rustc_span::{self, edition::Edition, Span, DUMMY_SP}; use std::borrow::Cow; use std::{fmt, mem}; @@ -813,52 +811,6 @@ pub fn pretty_printing_compatibility_hack(&self) -> bool { } false } - - // See issue #74616 for details - pub fn ident_name_compatibility_hack( - &self, - orig_span: Span, - source_map: &SourceMap, - ) -> Option<(Ident, bool)> { - if let NtIdent(ident, is_raw) = self { - if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { - let filename = source_map.span_to_filename(orig_span); - if let FileName::Real(RealFileName::Named(path)) = filename { - let matches_prefix = |prefix, filename| { - // Check for a path that ends with 'prefix*/src/' - let mut iter = path.components().rev(); - iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename) - && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src") - && iter - .next() - .and_then(|p| p.as_os_str().to_str()) - .map_or(false, |p| p.starts_with(prefix)) - }; - - if (macro_name == sym::impl_macros - && matches_prefix("time-macros-impl", "lib.rs")) - || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs")) - { - let snippet = source_map.span_to_snippet(orig_span); - if snippet.as_deref() == Ok("$name") { - return Some((*ident, *is_raw)); - } - } - - if macro_name == sym::tuple_from_req - && (matches_prefix("actix-web", "extract.rs") - || matches_prefix("actori-web", "extract.rs")) - { - let snippet = source_map.span_to_snippet(orig_span); - if snippet.as_deref() == Ok("$T") { - return Some((*ident, *is_raw)); - } - } - } - } - } - None - } } impl PartialEq for Nonterminal { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index b6195d3bbc4..837fad90580 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -2,16 +2,21 @@ use rustc_ast as ast; use rustc_ast::token; +use rustc_ast::token::Nonterminal; +use rustc_ast::token::NtIdent; use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens}; use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::Diagnostic; +use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; +use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::lexer::nfc_normalize; use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str}; use rustc_session::parse::ParseSess; +use rustc_span::hygiene::ExpnKind; use rustc_span::symbol::{self, kw, sym, Symbol}; -use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; +use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span}; use pm::bridge::{server, TokenTree}; use pm::{Delimiter, Level, LineColumn, Spacing}; @@ -174,9 +179,7 @@ macro_rules! op { } Interpolated(nt) => { - if let Some((name, is_raw)) = - nt.ident_name_compatibility_hack(span, sess.source_map()) - { + if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, sess) { TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span)) } else { let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No); @@ -711,3 +714,62 @@ fn source_text(&mut self, span: Self::Span) -> Option { self.sess.source_map().span_to_snippet(span).ok() } } + +// See issue #74616 for details +fn ident_name_compatibility_hack( + nt: &Nonterminal, + orig_span: Span, + sess: &ParseSess, +) -> Option<(rustc_span::symbol::Ident, bool)> { + if let NtIdent(ident, is_raw) = nt { + if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { + let source_map = sess.source_map(); + let filename = source_map.span_to_filename(orig_span); + if let FileName::Real(RealFileName::Named(path)) = filename { + let matches_prefix = |prefix, filename| { + // Check for a path that ends with 'prefix*/src/' + let mut iter = path.components().rev(); + iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename) + && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src") + && iter + .next() + .and_then(|p| p.as_os_str().to_str()) + .map_or(false, |p| p.starts_with(prefix)) + }; + + let time_macros_impl = + macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs"); + if time_macros_impl + || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs")) + { + let snippet = source_map.span_to_snippet(orig_span); + if snippet.as_deref() == Ok("$name") { + if time_macros_impl { + sess.buffer_lint_with_diagnostic( + &PROC_MACRO_BACK_COMPAT, + orig_span, + ast::CRATE_NODE_ID, + "using an old version of `time-macros-impl`", + BuiltinLintDiagnostics::ProcMacroBackCompat( + "the `time-macros-impl` crate will stop compiling in futures version of Rust. \ + Please update to the latest version of the `time` crate to avoid breakage".to_string()) + ); + } + return Some((*ident, *is_raw)); + } + } + + if macro_name == sym::tuple_from_req + && (matches_prefix("actix-web", "extract.rs") + || matches_prefix("actori-web", "extract.rs")) + { + let snippet = source_map.span_to_snippet(orig_span); + if snippet.as_deref() == Ok("$T") { + return Some((*ident, *is_raw)); + } + } + } + } + } + None +} diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7d5577cdca6..42ead89ca4f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -670,6 +670,9 @@ fn lookup_with_diagnostics( json ); } + BuiltinLintDiagnostics::ProcMacroBackCompat(note) => { + db.note(¬e); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index af48f6c2a5d..005c4f9f6ea 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -6,7 +6,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use crate::{declare_lint, declare_lint_pass}; +use crate::{declare_lint, declare_lint_pass, FutureBreakage}; use rustc_span::edition::Edition; declare_lint! { @@ -2955,6 +2955,7 @@ SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, DISJOINT_CAPTURE_DROP_REORDER, LEGACY_DERIVE_HELPERS, + PROC_MACRO_BACK_COMPAT, ] } @@ -3082,3 +3083,53 @@ edition: None, }; } + +declare_lint! { + /// The `proc_macro_back_compat` lint detects uses of old versions of certain + /// proc-macro crates, which have hardcoded workarounds in the compiler. + /// + /// ### Example + /// + /// ```rust,ignore (needs-dependency) + /// + /// use time_macros_impl::impl_macros; + /// struct Foo; + /// impl_macros!(Foo); + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: using an old version of `time-macros-impl` + /// ::: $DIR/group-compat-hack.rs:27:5 + /// | + /// LL | impl_macros!(Foo); + /// | ------------------ in this macro invocation + /// | + /// = note: `#[warn(proc_macro_back_compat)]` on by default + /// = 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 #83125 + /// = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage + /// = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + /// ``` + /// + /// ### Explanation + /// + /// Eventually, the backwards-compatibility hacks present in the compiler will be removed, + /// causing older versions of certain crates to stop compiling. + /// This is a [future-incompatible] lint to ease the transition to an error. + /// See [issue #83125] for more details. + /// + /// [issue #83125]: https://github.com/rust-lang/rust/issues/83125 + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub PROC_MACRO_BACK_COMPAT, + Warn, + "detects usage of old versions of certain proc-macro crates", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #83125 ", + edition: None, + future_breakage: Some(FutureBreakage { + date: None + }) + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4c7d3f6c8c0..400b367095e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -266,6 +266,7 @@ pub enum BuiltinLintDiagnostics { PatternsInFnsWithoutBody(Span, Ident), LegacyDeriveHelpers(Span), ExternDepSpec(String, ExternDepSpec), + ProcMacroBackCompat(String), } /// Lints that are buffered up early on in the `Session` before the diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs index 652fabf34ac..7f3f5e36f50 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs @@ -24,7 +24,8 @@ macro_rules! other { } struct Foo; - impl_macros!(Foo); + impl_macros!(Foo); //~ WARN using an old version + //~| WARN this was previously arrays!(Foo); other!(Foo); } @@ -40,7 +41,8 @@ macro_rules! other { } struct Foo; - impl_macros!(Foo); + impl_macros!(Foo); //~ WARN using an old version + //~| WARN this was previously arrays!(Foo); other!(Foo); } diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr new file mode 100644 index 00000000000..9370440a635 --- /dev/null +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr @@ -0,0 +1,70 @@ +warning: using an old version of `time-macros-impl` + --> $DIR/time-macros-impl/src/lib.rs:5:32 + | +LL | #[my_macro] struct One($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:27:5 + | +LL | impl_macros!(Foo); + | ------------------ in this macro invocation + | + = note: `#[warn(proc_macro_back_compat)]` on by default + = 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 #83125 + = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: using an old version of `time-macros-impl` + --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 + | +LL | #[my_macro] struct One($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:44:5 + | +LL | impl_macros!(Foo); + | ------------------ in this macro invocation + | + = 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 #83125 + = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 2 warnings emitted + +Future incompatibility report: Future breakage date: None, diagnostic: +warning: using an old version of `time-macros-impl` + --> $DIR/time-macros-impl/src/lib.rs:5:32 + | +LL | #[my_macro] struct One($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:27:5 + | +LL | impl_macros!(Foo); + | ------------------ in this macro invocation + | + = note: `#[warn(proc_macro_back_compat)]` on by default + = 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 #83125 + = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage date: None, diagnostic: +warning: using an old version of `time-macros-impl` + --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 + | +LL | #[my_macro] struct One($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:44:5 + | +LL | impl_macros!(Foo); + | ------------------ in this macro invocation + | + = 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 #83125 + = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout index c6b18ab674b..468cb511915 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout @@ -1,10 +1,10 @@ Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:13: 44:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:12: 45:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#28) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:52:21: 52:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:59:21: 59:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:66:21: 66:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:73:21: 73:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:30:12: 30:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:18: 44:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:61:21: 61:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:68:21: 68:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:75:21: 75:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] From d7ab3c77b3259e25e15d77b6939af4ba8d3be4c0 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Mon, 15 Mar 2021 17:57:53 +0800 Subject: [PATCH 18/23] Add `rustc_interface::interface::Config::parse_sess_created` --- compiler/rustc_driver/src/lib.rs | 2 ++ compiler/rustc_interface/src/interface.rs | 9 ++++++++- src/librustdoc/core.rs | 1 + src/librustdoc/doctest.rs | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 79bb21b29fc..25a78041c00 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -215,6 +215,7 @@ fn run_compiler( diagnostic_output, stderr: None, lint_caps: Default::default(), + parse_sess_created: None, register_lints: None, override_queries: None, make_codegen_backend: make_codegen_backend.take().unwrap(), @@ -298,6 +299,7 @@ fn run_compiler( diagnostic_output, stderr: None, lint_caps: Default::default(), + parse_sess_created: None, register_lints: None, override_queries: None, make_codegen_backend: make_codegen_backend.unwrap(), diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 502e7155c2e..14bffb54e7a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -142,6 +142,9 @@ pub struct Config { pub lint_caps: FxHashMap, + /// This is a callback from the driver that is called when [`ParseSess`] is created. + pub parse_sess_created: Option>, + /// This is a callback from the driver that is called when we're registering lints; /// it is called during plugin registration when we have the LintStore in a non-shared state. /// @@ -166,7 +169,7 @@ pub struct Config { pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R) -> R { let registry = &config.registry; - let (sess, codegen_backend) = util::create_session( + let (mut sess, codegen_backend) = util::create_session( config.opts, config.crate_cfg, config.diagnostic_output, @@ -177,6 +180,10 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R registry.clone(), ); + if let Some(parse_sess_created) = config.parse_sess_created { + parse_sess_created(&mut Lrc::get_mut(&mut sess).unwrap().parse_sess); + } + let compiler = Compiler { sess, codegen_backend, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e9c32396e84..c5b5ab0f3d0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -311,6 +311,7 @@ impl<'tcx> DocContext<'tcx> { diagnostic_output: DiagnosticOutput::Default, stderr: None, lint_caps, + parse_sess_created: None, register_lints: Some(box crate::lint::register_lints), override_queries: Some(|_sess, providers, _external_providers| { // Most lints will require typechecking, so just don't run them. diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 64375964e70..80e2e23eadd 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -95,6 +95,7 @@ diagnostic_output: DiagnosticOutput::Default, stderr: None, lint_caps, + parse_sess_created: None, register_lints: Some(box crate::lint::register_lints), override_queries: None, make_codegen_backend: None, From 176bb6bd38dc73557dc6947077f7239dda7b64ef Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Mon, 15 Mar 2021 18:24:28 +0800 Subject: [PATCH 19/23] Use `rustc_interface::interface::Config::parse_sess_created` in Clippy --- src/tools/clippy/src/driver.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 30272c9b800..b6aed862e89 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -15,7 +15,7 @@ extern crate rustc_span; use rustc_interface::interface; -use rustc_session::Session; +use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; use rustc_tools_util::VersionInfo; @@ -63,8 +63,8 @@ fn test_arg_value() { assert_eq!(arg_value(args, "--foo", |_| true), None); } -fn track_clippy_args(sess: &Session, args_env_var: &Option) { - sess.parse_sess.env_depinfo.borrow_mut().insert(( +fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option) { + parse_sess.env_depinfo.get_mut().insert(( Symbol::intern("CLIPPY_ARGS"), args_env_var.as_deref().map(Symbol::intern), )); @@ -81,14 +81,9 @@ struct RustcCallbacks { impl rustc_driver::Callbacks for RustcCallbacks { fn config(&mut self, config: &mut interface::Config) { - let previous = config.register_lints.take(); let clippy_args_var = self.clippy_args_var.take(); - config.register_lints = Some(Box::new(move |sess, lint_store| { - if let Some(ref previous) = previous { - (previous)(sess, lint_store); - } - - track_clippy_args(sess, &clippy_args_var); + config.parse_sess_created = Some(Box::new(move |parse_sess| { + track_clippy_args(parse_sess, &clippy_args_var); })); } } @@ -101,6 +96,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks { fn config(&mut self, config: &mut interface::Config) { let previous = config.register_lints.take(); let clippy_args_var = self.clippy_args_var.take(); + config.parse_sess_created = Some(Box::new(move |parse_sess| { + track_clippy_args(parse_sess, &clippy_args_var); + })); config.register_lints = Some(Box::new(move |sess, mut lint_store| { // technically we're ~guaranteed that this is none but might as well call anything that // is there already. Certainly it can't hurt. @@ -108,8 +106,6 @@ fn config(&mut self, config: &mut interface::Config) { (previous)(sess, lint_store); } - track_clippy_args(sess, &clippy_args_var); - let conf = clippy_lints::read_conf(&[], &sess); clippy_lints::register_plugins(&mut lint_store, &sess, &conf); clippy_lints::register_pre_expansion_lints(&mut lint_store); From ebe51cfcedba0eaf8038672c594aea4bb3cf4c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 15 Mar 2021 13:55:56 +0200 Subject: [PATCH 20/23] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index d54e1157b66..5ba7852cf15 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit d54e1157b66017e4aae38328cd213286e39ca130 +Subproject commit 5ba7852cf153688d5b5035a9a2a2145aa7334d79 From 5eae9af193efca654a4e20ec0766781c24b7eb87 Mon Sep 17 00:00:00 2001 From: Smitty Date: Mon, 15 Mar 2021 08:11:02 -0400 Subject: [PATCH 21/23] Custom error on literal names from other languages This detects all Java literal types and all single word C data types, and suggests the corresponding Rust literal type. --- .../rustc_resolve/src/late/diagnostics.rs | 26 +++++++ src/test/ui/lint/recommend-literal.rs | 35 +++++++++ src/test/ui/lint/recommend-literal.stderr | 72 +++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 src/test/ui/lint/recommend-literal.rs create mode 100644 src/test/ui/lint/recommend-literal.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e7b3d459766..e85d78db22c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -563,6 +563,15 @@ pub(crate) fn smart_resolve_report_errors( } } } + } else if err_code == &rustc_errors::error_code!(E0412) { + if let Some(correct) = Self::likely_rust_type(path) { + err.span_suggestion( + span, + "perhaps you intended to use this type", + correct.to_string(), + Applicability::MaybeIncorrect, + ); + } } } @@ -1243,6 +1252,23 @@ fn lookup_typo_candidate( } } + // Returns the name of the Rust type approximately corresponding to + // a type name in another programming language. + fn likely_rust_type(path: &[Segment]) -> Option { + let name = path[path.len() - 1].ident.as_str(); + // Common Java types + Some(match &*name { + "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes. + "short" => sym::i16, + "boolean" => sym::bool, + "int" => sym::i32, + "long" => sym::i64, + "float" => sym::f32, + "double" => sym::f64, + _ => return None, + }) + } + /// Only used in a specific case of type ascription suggestions fn get_colon_suggestion_span(&self, start: Span) -> Span { let sm = self.r.session.source_map(); diff --git a/src/test/ui/lint/recommend-literal.rs b/src/test/ui/lint/recommend-literal.rs new file mode 100644 index 00000000000..f60d3d10dce --- /dev/null +++ b/src/test/ui/lint/recommend-literal.rs @@ -0,0 +1,35 @@ +type Real = double; +//~^ ERROR cannot find type `double` in this scope +//~| HELP perhaps you intended to use this type + +fn main() { + let x: Real = 3.5; + let y: long = 74802374902374923; + //~^ ERROR cannot find type `long` in this scope + //~| HELP perhaps you intended to use this type +} + +fn z(a: boolean) { + //~^ ERROR cannot find type `boolean` in this scope + //~| HELP perhaps you intended to use this type +} + +fn a() -> byte { +//~^ ERROR cannot find type `byte` in this scope +//~| HELP perhaps you intended to use this type + 3 +} + +struct Data { //~ HELP you might be missing a type parameter + width: float, + //~^ ERROR cannot find type `float` in this scope + //~| HELP perhaps you intended to use this type + depth: Option, + //~^ ERROR cannot find type `int` in this scope + //~| HELP perhaps you intended to use this type +} + +trait Stuff {} +impl Stuff for short {} +//~^ ERROR cannot find type `short` in this scope +//~| HELP perhaps you intended to use this type diff --git a/src/test/ui/lint/recommend-literal.stderr b/src/test/ui/lint/recommend-literal.stderr new file mode 100644 index 00000000000..b01073b42b8 --- /dev/null +++ b/src/test/ui/lint/recommend-literal.stderr @@ -0,0 +1,72 @@ +error[E0412]: cannot find type `double` in this scope + --> $DIR/recommend-literal.rs:1:13 + | +LL | type Real = double; + | ^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f64` + +error[E0412]: cannot find type `long` in this scope + --> $DIR/recommend-literal.rs:7:12 + | +LL | let y: long = 74802374902374923; + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i64` + +error[E0412]: cannot find type `boolean` in this scope + --> $DIR/recommend-literal.rs:12:9 + | +LL | fn z(a: boolean) { + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `byte` in this scope + --> $DIR/recommend-literal.rs:17:11 + | +LL | fn a() -> byte { + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `u8` + +error[E0412]: cannot find type `float` in this scope + --> $DIR/recommend-literal.rs:24:12 + | +LL | width: float, + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f32` + +error[E0412]: cannot find type `int` in this scope + --> $DIR/recommend-literal.rs:27:19 + | +LL | depth: Option, + | ^^^ not found in this scope + | +help: perhaps you intended to use this type + | +LL | depth: Option, + | ^^^ +help: you might be missing a type parameter + | +LL | struct Data { + | ^^^^^ + +error[E0412]: cannot find type `short` in this scope + --> $DIR/recommend-literal.rs:33:16 + | +LL | impl Stuff for short {} + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i16` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0412`. From 4709dcd476540621f7fb023ae68b4f916d857278 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Mon, 15 Mar 2021 20:44:48 +0800 Subject: [PATCH 22/23] Change the `.unwrap` to `.expect` with a helpful message --- compiler/rustc_interface/src/interface.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 14bffb54e7a..a1090ee316d 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -181,7 +181,11 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R ); if let Some(parse_sess_created) = config.parse_sess_created { - parse_sess_created(&mut Lrc::get_mut(&mut sess).unwrap().parse_sess); + parse_sess_created( + &mut Lrc::get_mut(&mut sess) + .expect("create_session() should never share the returned session") + .parse_sess, + ); } let compiler = Compiler { From 0bbfd548ecf48e17c9db43160aa3784caa2fcd47 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Mon, 15 Mar 2021 21:16:39 +0800 Subject: [PATCH 23/23] Fix `src/test/run-make-fulldeps/issue-19371` --- src/test/run-make-fulldeps/issue-19371/foo.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index fdd7e8b24c5..4acabbb70ed 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -57,6 +57,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { diagnostic_output: DiagnosticOutput::Default, stderr: None, lint_caps: Default::default(), + parse_sess_created: None, register_lints: None, override_queries: None, make_codegen_backend: None,