Skip to content

Commit 02b0479

Browse files
committed
Auto merge of #52568 - oli-obk:span_bug_error, r=varkor
Fix loop label resolution around constants And make `delay_span_bug` a little more helpful r? @varkor fixes #52442 fixes #52443
2 parents 67f9c71 + bab5eb4 commit 02b0479

File tree

12 files changed

+151
-46
lines changed

12 files changed

+151
-46
lines changed

src/librustc/hir/lowering.rs

+22-36
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ pub struct LoweringContext<'a> {
104104
loop_scopes: Vec<NodeId>,
105105
is_in_loop_condition: bool,
106106
is_in_trait_impl: bool,
107-
is_in_anon_const: bool,
108107

109108
/// What to do when we encounter either an "anonymous lifetime
110109
/// reference". The term "anonymous" is meant to encompass both
@@ -232,7 +231,6 @@ pub fn lower_crate(
232231
node_id_to_hir_id: IndexVec::new(),
233232
is_generator: false,
234233
is_in_trait_impl: false,
235-
is_in_anon_const: false,
236234
lifetimes_to_define: Vec::new(),
237235
is_collecting_in_band_lifetimes: false,
238236
in_scope_lifetimes: Vec::new(),
@@ -972,26 +970,22 @@ impl<'a> LoweringContext<'a> {
972970
}
973971

974972
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
975-
let target_id = if self.is_in_anon_const {
976-
Err(hir::LoopIdError::OutsideLoopScope)
977-
} else {
978-
match destination {
979-
Some((id, _)) => {
980-
if let Def::Label(loop_id) = self.expect_full_def(id) {
981-
Ok(self.lower_node_id(loop_id).node_id)
982-
} else {
983-
Err(hir::LoopIdError::UnresolvedLabel)
984-
}
985-
}
986-
None => {
987-
self.loop_scopes
988-
.last()
989-
.map(|innermost_loop_id| *innermost_loop_id)
990-
.map(|id| Ok(self.lower_node_id(id).node_id))
991-
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
992-
.into()
973+
let target_id = match destination {
974+
Some((id, _)) => {
975+
if let Def::Label(loop_id) = self.expect_full_def(id) {
976+
Ok(self.lower_node_id(loop_id).node_id)
977+
} else {
978+
Err(hir::LoopIdError::UnresolvedLabel)
993979
}
994980
}
981+
None => {
982+
self.loop_scopes
983+
.last()
984+
.map(|innermost_loop_id| *innermost_loop_id)
985+
.map(|id| Ok(self.lower_node_id(id).node_id))
986+
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
987+
.into()
988+
}
995989
};
996990
hir::Destination {
997991
label: self.lower_label(destination.map(|(_, label)| label)),
@@ -3490,22 +3484,14 @@ impl<'a> LoweringContext<'a> {
34903484
}
34913485

34923486
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
3493-
let was_in_loop_condition = self.is_in_loop_condition;
3494-
self.is_in_loop_condition = false;
3495-
let was_in_anon_const = self.is_in_anon_const;
3496-
self.is_in_anon_const = true;
3497-
3498-
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
3499-
let anon_const = hir::AnonConst {
3500-
id: node_id,
3501-
hir_id,
3502-
body: self.lower_body(None, |this| this.lower_expr(&c.value)),
3503-
};
3504-
3505-
self.is_in_anon_const = was_in_anon_const;
3506-
self.is_in_loop_condition = was_in_loop_condition;
3507-
3508-
anon_const
3487+
self.with_new_scopes(|this| {
3488+
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(c.id);
3489+
hir::AnonConst {
3490+
id: node_id,
3491+
hir_id,
3492+
body: this.lower_body(None, |this| this.lower_expr(&c.value)),
3493+
}
3494+
})
35093495
}
35103496

35113497
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {

src/librustc/session/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
11931193
"run all passes except codegen; no output"),
11941194
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
11951195
"treat all errors that occur as bugs"),
1196+
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
1197+
"immediately print bugs registered with `delay_span_bug`"),
11961198
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
11971199
"show macro backtraces even for non-local macros"),
11981200
teach: bool = (false, parse_bool, [TRACKED],
@@ -3133,6 +3135,10 @@ mod tests {
31333135
opts.debugging_opts.treat_err_as_bug = true;
31343136
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
31353137

3138+
opts = reference.clone();
3139+
opts.debugging_opts.report_delayed_bugs = true;
3140+
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
3141+
31363142
opts = reference.clone();
31373143
opts.debugging_opts.continue_parse_after_error = true;
31383144
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());

src/librustc/session/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ pub fn build_session_with_codemap(
10001000
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
10011001

10021002
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
1003+
let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
10031004

10041005
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
10051006

@@ -1045,6 +1046,7 @@ pub fn build_session_with_codemap(
10451046
errors::HandlerFlags {
10461047
can_emit_warnings,
10471048
treat_err_as_bug,
1049+
report_delayed_bugs,
10481050
external_macro_backtrace,
10491051
..Default::default()
10501052
},

src/librustc_errors/diagnostic_builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<'a> DiagnosticBuilder<'a> {
132132
/// locally in whichever way makes the most sense.
133133
pub fn delay_as_bug(&mut self) {
134134
self.level = Level::Bug;
135-
*self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
135+
self.handler.delay_as_bug(self.diagnostic.clone());
136136
self.cancel();
137137
}
138138

src/librustc_errors/lib.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ pub struct Handler {
274274
err_count: AtomicUsize,
275275
emitter: Lock<Box<dyn Emitter + sync::Send>>,
276276
continue_after_error: LockCell<bool>,
277-
delayed_span_bug: Lock<Option<Diagnostic>>,
277+
delayed_span_bugs: Lock<Vec<Diagnostic>>,
278278

279279
// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
280280
// emitting the same diagnostic with extended help (`--teach`) twice, which
@@ -299,9 +299,25 @@ thread_local!(pub static TRACK_DIAGNOSTICS: Cell<fn(&Diagnostic)> =
299299
pub struct HandlerFlags {
300300
pub can_emit_warnings: bool,
301301
pub treat_err_as_bug: bool,
302+
pub report_delayed_bugs: bool,
302303
pub external_macro_backtrace: bool,
303304
}
304305

306+
impl Drop for Handler {
307+
fn drop(&mut self) {
308+
if self.err_count() == 0 {
309+
let mut bugs = self.delayed_span_bugs.borrow_mut();
310+
let has_bugs = !bugs.is_empty();
311+
for bug in bugs.drain(..) {
312+
DiagnosticBuilder::new_diagnostic(self, bug).emit();
313+
}
314+
if has_bugs {
315+
panic!("no errors encountered even though `delay_span_bug` issued");
316+
}
317+
}
318+
}
319+
}
320+
305321
impl Handler {
306322
pub fn with_tty_emitter(color_config: ColorConfig,
307323
can_emit_warnings: bool,
@@ -346,7 +362,7 @@ impl Handler {
346362
err_count: AtomicUsize::new(0),
347363
emitter: Lock::new(e),
348364
continue_after_error: LockCell::new(true),
349-
delayed_span_bug: Lock::new(None),
365+
delayed_span_bugs: Lock::new(Vec::new()),
350366
taught_diagnostics: Lock::new(FxHashSet()),
351367
emitted_diagnostic_codes: Lock::new(FxHashSet()),
352368
emitted_diagnostics: Lock::new(FxHashSet()),
@@ -503,11 +519,18 @@ impl Handler {
503519
}
504520
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
505521
if self.flags.treat_err_as_bug {
522+
// FIXME: don't abort here if report_delayed_bugs is off
506523
self.span_bug(sp, msg);
507524
}
508525
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
509526
diagnostic.set_span(sp.into());
510-
*self.delayed_span_bug.borrow_mut() = Some(diagnostic);
527+
self.delay_as_bug(diagnostic);
528+
}
529+
fn delay_as_bug(&self, diagnostic: Diagnostic) {
530+
if self.flags.report_delayed_bugs {
531+
DiagnosticBuilder::new_diagnostic(self, diagnostic.clone()).emit();
532+
}
533+
self.delayed_span_bugs.borrow_mut().push(diagnostic);
511534
}
512535
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
513536
self.emit(&sp.into(), msg, Bug);
@@ -615,9 +638,6 @@ impl Handler {
615638

616639
pub fn abort_if_errors(&self) {
617640
if self.err_count() == 0 {
618-
if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
619-
DiagnosticBuilder::new_diagnostic(self, bug).emit();
620-
}
621641
return;
622642
}
623643
FatalError.raise();

src/librustc_resolve/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2359,7 +2359,9 @@ impl<'a> Resolver<'a> {
23592359
where F: FnOnce(&mut Resolver)
23602360
{
23612361
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
2362+
self.label_ribs.push(Rib::new(ConstantItemRibKind));
23622363
f(self);
2364+
self.label_ribs.pop();
23632365
self.ribs[ValueNS].pop();
23642366
}
23652367

src/librustc_typeck/check/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -857,9 +857,6 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
857857
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
858858

859859
// Gather locals in statics (because of block expressions).
860-
// This is technically unnecessary because locals in static items are forbidden,
861-
// but prevents type checking from blowing up before const checking can properly
862-
// emit an error.
863860
GatherLocalsVisitor { fcx: &fcx }.visit_body(body);
864861

865862
fcx.check_expr_coercable_to_type(&body.value, expected_type);

src/librustdoc/core.rs

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::C
162162
errors::HandlerFlags {
163163
can_emit_warnings: true,
164164
treat_err_as_bug: false,
165+
report_delayed_bugs: false,
165166
external_macro_backtrace: false,
166167
..Default::default()
167168
},

src/test/ui/const-eval/issue-52442.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
[(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0019]: constant contains unimplemented expression type
2+
--> $DIR/issue-52442.rs:12:14
3+
|
4+
LL | [(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
5+
| ^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0019`.

src/test/ui/const-eval/issue-52443.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
[(); & { loop { continue } } ]; //~ ERROR mismatched types
13+
[(); loop { break }]; //~ ERROR mismatched types
14+
[(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type
15+
[(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
16+
//~^ ERROR constant contains unimplemented expression type
17+
//~| ERROR could not evaluate repeat length
18+
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-52443.rs:12:10
3+
|
4+
LL | [(); & { loop { continue } } ]; //~ ERROR mismatched types
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| expected usize, found reference
8+
| help: consider removing the borrow: `{ loop { continue } }`
9+
|
10+
= note: expected type `usize`
11+
found type `&_`
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/issue-52443.rs:13:17
15+
|
16+
LL | [(); loop { break }]; //~ ERROR mismatched types
17+
| ^^^^^ expected (), found usize
18+
|
19+
= note: expected type `()`
20+
found type `usize`
21+
22+
error[E0019]: constant contains unimplemented expression type
23+
--> $DIR/issue-52443.rs:14:11
24+
|
25+
LL | [(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type
26+
| ^^^^^^^^^^^^^^^^^^
27+
28+
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
29+
--> $DIR/issue-52443.rs:15:21
30+
|
31+
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
32+
| ^^^^^^^^
33+
34+
error[E0019]: constant contains unimplemented expression type
35+
--> $DIR/issue-52443.rs:15:21
36+
|
37+
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
38+
| ^^^^^^^^
39+
40+
error[E0080]: could not evaluate repeat length
41+
--> $DIR/issue-52443.rs:15:10
42+
|
43+
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
44+
| ^^^^^^^^^^^--------^^^^^^^
45+
| |
46+
| calling non-const fn `<I as std::iter::IntoIterator><std::ops::RangeFrom<usize>>::into_iter`
47+
48+
error: aborting due to 6 previous errors
49+
50+
Some errors occurred: E0015, E0019, E0080, E0308.
51+
For more information about an error, try `rustc --explain E0015`.

0 commit comments

Comments
 (0)