Skip to content

Commit 0f26ee4

Browse files
committed
Auto merge of rust-lang#129202 - matthiaskrgr:rollup-wev7uur, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#128989 (Emit an error for invalid use of the linkage attribute) - rust-lang#129167 (mir/pretty: use `Option` instead of `Either<Once, Empty>`) - rust-lang#129168 (Return correct HirId when finding body owner in diagnostics) - rust-lang#129191 (rustdoc-json: Clean up serialization and printing.) - rust-lang#129192 (Remove useless attributes in merged doctest generated code) - rust-lang#129196 (Remove a useless ref/id/ref round-trip from `pattern_from_hir`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9b318d2 + 4e6147d commit 0f26ee4

File tree

15 files changed

+357
-101
lines changed

15 files changed

+357
-101
lines changed

compiler/rustc_middle/src/hir/map/mod.rs

+27-37
Original file line numberDiff line numberDiff line change
@@ -554,53 +554,43 @@ impl<'hir> Map<'hir> {
554554
/// }
555555
/// ```
556556
pub fn get_fn_id_for_return_block(self, id: HirId) -> Option<HirId> {
557-
let mut iter = self.parent_iter(id).peekable();
558-
let mut ignore_tail = false;
559-
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) {
560-
// When dealing with `return` statements, we don't care about climbing only tail
561-
// expressions.
562-
ignore_tail = true;
563-
}
557+
let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id));
558+
559+
// Return `None` if the `id` expression is not the returned value of the enclosing body
560+
let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable();
561+
while let Some(cur_id) = iter.next() {
562+
if enclosing_body_owner == cur_id {
563+
break;
564+
}
565+
566+
// A return statement is always the value returned from the enclosing body regardless of
567+
// what the parent expressions are.
568+
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) {
569+
break;
570+
}
564571

565-
let mut prev_hir_id = None;
566-
while let Some((hir_id, node)) = iter.next() {
567-
if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
568-
match next_node {
569-
Node::Block(Block { expr: None, .. }) => return None,
570-
// The current node is not the tail expression of its parent.
571-
Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None,
572+
// If the current expression's value doesnt get used as the parent expressions value then return `None`
573+
if let Some(&parent_id) = iter.peek() {
574+
match self.tcx.hir_node(parent_id) {
575+
// The current node is not the tail expression of the block expression parent expr.
576+
Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
572577
Node::Block(Block { expr: Some(e), .. })
573578
if matches!(e.kind, ExprKind::If(_, _, None)) =>
574579
{
575580
return None;
576581
}
582+
583+
// The current expression's value does not pass up through these parent expressions
584+
Node::Block(Block { expr: None, .. })
585+
| Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
586+
| Node::LetStmt(..) => return None,
587+
577588
_ => {}
578589
}
579590
}
580-
match node {
581-
Node::Item(_)
582-
| Node::ForeignItem(_)
583-
| Node::TraitItem(_)
584-
| Node::Expr(Expr { kind: ExprKind::Closure(_), .. })
585-
| Node::ImplItem(_)
586-
// The input node `id` must be enclosed in the method's body as opposed
587-
// to some other place such as its return type (fixes #114918).
588-
// We verify that indirectly by checking that the previous node is the
589-
// current node's body
590-
if node.body_id().map(|b| b.hir_id) == prev_hir_id => {
591-
return Some(hir_id)
592-
}
593-
// Ignore `return`s on the first iteration
594-
Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
595-
| Node::LetStmt(_) => {
596-
return None;
597-
}
598-
_ => {}
599-
}
600-
601-
prev_hir_id = Some(hir_id);
602591
}
603-
None
592+
593+
Some(enclosing_body_owner)
604594
}
605595

606596
/// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no

compiler/rustc_middle/src/mir/pretty.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1418,21 +1418,19 @@ pub fn write_allocations<'tcx>(
14181418
alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id())
14191419
}
14201420

1421-
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
1421+
fn alloc_id_from_const_val(val: ConstValue<'_>) -> Option<AllocId> {
14221422
match val {
1423-
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
1424-
Either::Left(std::iter::once(ptr.provenance.alloc_id()))
1425-
}
1426-
ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()),
1427-
ConstValue::ZeroSized => Either::Right(std::iter::empty()),
1423+
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()),
1424+
ConstValue::Scalar(interpret::Scalar::Int { .. }) => None,
1425+
ConstValue::ZeroSized => None,
14281426
ConstValue::Slice { .. } => {
14291427
// `u8`/`str` slices, shouldn't contain pointers that we want to print.
1430-
Either::Right(std::iter::empty())
1428+
None
14311429
}
14321430
ConstValue::Indirect { alloc_id, .. } => {
14331431
// FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR.
14341432
// Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor.
1435-
Either::Left(std::iter::once(alloc_id))
1433+
Some(alloc_id)
14361434
}
14371435
}
14381436
}
@@ -1443,7 +1441,9 @@ pub fn write_allocations<'tcx>(
14431441
match c.const_ {
14441442
Const::Ty(_, _) | Const::Unevaluated(..) => {}
14451443
Const::Val(val, _) => {
1446-
self.0.extend(alloc_ids_from_const_val(val));
1444+
if let Some(id) = alloc_id_from_const_val(val) {
1445+
self.0.insert(id);
1446+
}
14471447
}
14481448
}
14491449
}

compiler/rustc_mir_build/src/thir/cx/mod.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir as hir;
88
use rustc_hir::def::DefKind;
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_hir::{HirId, Node};
11+
use rustc_hir::HirId;
1212
use rustc_middle::bug;
1313
use rustc_middle::middle::region;
1414
use rustc_middle::thir::*;
@@ -110,11 +110,7 @@ impl<'tcx> Cx<'tcx> {
110110
}
111111

112112
#[instrument(level = "debug", skip(self))]
113-
fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
114-
let p = match self.tcx.hir_node(p.hir_id) {
115-
Node::Pat(p) => p,
116-
node => bug!("pattern became {:?}", node),
117-
};
113+
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
118114
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
119115
}
120116

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,10 @@ passes_link_section =
430430
.warn = {-passes_previously_accepted}
431431
.label = not a function or static
432432
433+
passes_linkage =
434+
attribute should be applied to a function or static
435+
.label = not a function definition or static
436+
433437
passes_macro_export =
434438
`#[macro_export]` only has an effect on macro definitions
435439

compiler/rustc_passes/src/check_attr.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
243243
[sym::coroutine, ..] => {
244244
self.check_coroutine(attr, target);
245245
}
246+
[sym::linkage, ..] => self.check_linkage(attr, span, target),
246247
[
247248
// ok
248249
sym::allow
@@ -256,7 +257,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
256257
| sym::cfi_encoding // FIXME(cfi_encoding)
257258
| sym::may_dangle // FIXME(dropck_eyepatch)
258259
| sym::pointee // FIXME(derive_smart_pointer)
259-
| sym::linkage // FIXME(linkage)
260260
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
261261
| sym::used // handled elsewhere to restrict to static items
262262
| sym::repr // handled elsewhere to restrict to type decls items
@@ -2347,6 +2347,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
23472347
}
23482348
}
23492349
}
2350+
2351+
fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
2352+
match target {
2353+
Target::Fn
2354+
| Target::Method(..)
2355+
| Target::Static
2356+
| Target::ForeignStatic
2357+
| Target::ForeignFn => {}
2358+
_ => {
2359+
self.dcx().emit_err(errors::Linkage { attr_span: attr.span, span });
2360+
}
2361+
}
2362+
}
23502363
}
23512364

23522365
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {

compiler/rustc_passes/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,15 @@ pub struct CoroutineOnNonClosure {
643643
pub span: Span,
644644
}
645645

646+
#[derive(Diagnostic)]
647+
#[diag(passes_linkage)]
648+
pub struct Linkage {
649+
#[primary_span]
650+
pub attr_span: Span,
651+
#[label]
652+
pub span: Span,
653+
}
654+
646655
#[derive(Diagnostic)]
647656
#[diag(passes_empty_confusables)]
648657
pub(crate) struct EmptyConfusables {

src/librustdoc/doctest/runner.rs

-4
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ impl DocTestRunner {
7575
#![allow(internal_features)]
7676
#![feature(test)]
7777
#![feature(rustc_attrs)]
78-
#![feature(coverage_attribute)]
7978
"
8079
.to_string();
8180

@@ -135,7 +134,6 @@ mod __doctest_mod {{
135134
}}
136135
137136
#[rustc_main]
138-
#[coverage(off)]
139137
fn main() -> std::process::ExitCode {{
140138
const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}];
141139
let bin_marker = std::ffi::OsStr::new(__doctest_mod::BIN_OPTION);
@@ -235,11 +233,9 @@ fn main() {returns_result} {{
235233
writeln!(
236234
output,
237235
"
238-
#[rustc_test_marker = {test_name:?}]
239236
pub const TEST: test::TestDescAndFn = test::TestDescAndFn::new_doctest(
240237
{test_name:?}, {ignore}, {file:?}, {line}, {no_run}, {should_panic},
241238
test::StaticTestFn(
242-
#[coverage(off)]
243239
|| {{{runner}}},
244240
));
245241
}}",

src/librustdoc/json/mod.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ pub(crate) struct JsonRenderer<'tcx> {
3939
/// A mapping of IDs that contains all local items for this crate which gets output as a top
4040
/// level field of the JSON blob.
4141
index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
42-
/// The directory where the blob will be written to.
43-
out_path: Option<PathBuf>,
42+
/// The directory where the JSON blob should be written to.
43+
///
44+
/// If this is `None`, the blob will be printed to `stdout` instead.
45+
out_dir: Option<PathBuf>,
4446
cache: Rc<Cache>,
4547
imported_items: DefIdSet,
4648
}
@@ -101,18 +103,20 @@ impl<'tcx> JsonRenderer<'tcx> {
101103
.unwrap_or_default()
102104
}
103105

104-
fn write<T: Write>(
106+
fn serialize_and_write<T: Write>(
105107
&self,
106-
output: types::Crate,
108+
output_crate: types::Crate,
107109
mut writer: BufWriter<T>,
108110
path: &str,
109111
) -> Result<(), Error> {
110-
self.tcx
111-
.sess
112-
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut writer, &output))
113-
.unwrap();
114-
try_err!(writer.flush(), path);
115-
Ok(())
112+
self.sess().time("rustdoc_json_serialize_and_write", || {
113+
try_err!(
114+
serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()),
115+
path
116+
);
117+
try_err!(writer.flush(), path);
118+
Ok(())
119+
})
116120
}
117121
}
118122

@@ -137,7 +141,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
137141
JsonRenderer {
138142
tcx,
139143
index: Rc::new(RefCell::new(FxHashMap::default())),
140-
out_path: if options.output_to_stdout { None } else { Some(options.output) },
144+
out_dir: if options.output_to_stdout { None } else { Some(options.output) },
141145
cache: Rc::new(cache),
142146
imported_items,
143147
},
@@ -237,7 +241,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
237241
let index = (*self.index).clone().into_inner();
238242

239243
debug!("Constructing Output");
240-
let output = types::Crate {
244+
let output_crate = types::Crate {
241245
root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())),
242246
crate_version: self.cache.crate_version.clone(),
243247
includes_private: self.cache.document_private,
@@ -278,20 +282,20 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
278282
.collect(),
279283
format_version: types::FORMAT_VERSION,
280284
};
281-
if let Some(ref out_path) = self.out_path {
282-
let out_dir = out_path.clone();
285+
if let Some(ref out_dir) = self.out_dir {
283286
try_err!(create_dir_all(&out_dir), out_dir);
284287

285-
let mut p = out_dir;
286-
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
288+
let mut p = out_dir.clone();
289+
p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap());
287290
p.set_extension("json");
288-
self.write(
289-
output,
291+
292+
self.serialize_and_write(
293+
output_crate,
290294
BufWriter::new(try_err!(File::create(&p), p)),
291295
&p.display().to_string(),
292296
)
293297
} else {
294-
self.write(output, BufWriter::new(stdout()), "<stdout>")
298+
self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "<stdout>")
295299
}
296300
}
297301

tests/crashes/128810.rs

-25
This file was deleted.

tests/ui/attributes/linkage.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#![feature(linkage)]
2+
#![feature(stmt_expr_attributes)]
3+
#![deny(unused_attributes)]
4+
#![allow(dead_code)]
5+
6+
#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
7+
type InvalidTy = ();
8+
9+
#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
10+
mod invalid_module {}
11+
12+
#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
13+
struct F;
14+
15+
#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
16+
impl F {
17+
#[linkage = "weak"]
18+
fn valid(&self) {}
19+
}
20+
21+
#[linkage = "weak"]
22+
fn f() {
23+
#[linkage = "weak"]
24+
{
25+
1
26+
};
27+
//~^^^^ ERROR attribute should be applied to a function or static
28+
}
29+
30+
extern "C" {
31+
#[linkage = "weak"]
32+
static A: *const ();
33+
34+
#[linkage = "weak"]
35+
fn bar();
36+
}
37+
38+
fn main() {
39+
let _ = #[linkage = "weak"]
40+
(|| 1);
41+
//~^^ ERROR attribute should be applied to a function or static
42+
}

0 commit comments

Comments
 (0)