diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5608bd82fdacd..dad08e0bc92fd 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1304,6 +1304,15 @@ impl Attribute { Attribute::Unparsed(_) => false, } } + + pub fn is_prefix_attr_for_suggestions(&self) -> bool { + match self { + Attribute::Unparsed(attr) => attr.span.desugaring_kind().is_none(), + // Other parsed attributes that can appear on expressions originate from source and + // should make suggestions treat the expression like a prefixed form. + Attribute::Parsed(_) => true, + } + } } impl AttributeExt for Attribute { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ac77354f2a794..71c02dc32f6b5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -57,25 +57,7 @@ use crate::{ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { let has_attr = |id: HirId| -> bool { - for attr in self.tcx.hir_attrs(id) { - // For the purpose of rendering suggestions, disregard attributes - // that originate from desugaring of any kind. For example, `x?` - // desugars to `#[allow(unreachable_code)] match ...`. Failing to - // ignore the prefix attribute in the desugaring would cause this - // suggestion: - // - // let y: u32 = x?.try_into().unwrap(); - // ++++++++++++++++++++ - // - // to be rendered as: - // - // let y: u32 = (x?).try_into().unwrap(); - // + +++++++++++++++++++++ - if attr.span().desugaring_kind().is_none() { - return true; - } - } - false + self.tcx.hir_attrs(id).iter().any(hir::Attribute::is_prefix_attr_for_suggestions) }; // Special case: range expressions are desugared to struct literals in HIR, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 46aeec65fe2d7..352652413751e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -845,12 +845,7 @@ impl<'tcx> LateContext<'tcx> { /// be used for pretty-printing HIR by rustc_hir_pretty. pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { let has_attr = |id: hir::HirId| -> bool { - for attr in self.tcx.hir_attrs(id) { - if attr.span().desugaring_kind().is_none() { - return true; - } - } - false + self.tcx.hir_attrs(id).iter().any(hir::Attribute::is_prefix_attr_for_suggestions) }; expr.precedence(&has_attr) } diff --git a/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.rs b/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.rs new file mode 100644 index 0000000000000..2264d2ba44a89 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.rs @@ -0,0 +1,11 @@ +fn main() { + let _x = 30; + #[cfg_attr(, (cc))] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `,` + _x //~ ERROR mismatched types +} + +fn inline_case() { + let _x = 30; + #[inline] //~ ERROR `#[inline]` attribute cannot be used on expressions + _x //~ ERROR mismatched types +} diff --git a/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.stderr b/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.stderr new file mode 100644 index 0000000000000..ee62d232b12a7 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-parsed-span-issue-154801.stderr @@ -0,0 +1,42 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `,` + --> $DIR/cfg-attr-parsed-span-issue-154801.rs:3:16 + | +LL | #[cfg_attr(, (cc))] + | ^ + | + = note: for more information, visit +help: must be of the form + | +LL - #[cfg_attr(, (cc))] +LL + #[cfg_attr(predicate, attr1, attr2, ...)] + | + +error: `#[inline]` attribute cannot be used on expressions + --> $DIR/cfg-attr-parsed-span-issue-154801.rs:9:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error[E0308]: mismatched types + --> $DIR/cfg-attr-parsed-span-issue-154801.rs:4:5 + | +LL | fn main() { + | - expected `()` because of default return type +... +LL | _x + | ^^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/cfg-attr-parsed-span-issue-154801.rs:10:5 + | +LL | fn inline_case() { + | - help: try adding a return type: `-> i32` +... +LL | _x + | ^^ expected `()`, found integer + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`.