Skip to content

Commit 4dd6b09

Browse files
committed
Merge pull request #30844 from pnkfelix/pr30753-betaport-downgrade-struct-warn-to-err
[beta] downgrade struct warn to err
2 parents 2e48b59 + 5e2e81b commit 4dd6b09

File tree

8 files changed

+62
-21
lines changed

8 files changed

+62
-21
lines changed

src/librustc/lint/builtin.rs

+11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
1717
use lint::{LintPass, LateLintPass, LintArray};
1818

19+
// name of the future-incompatible group
20+
pub const FUTURE_INCOMPATIBLE: &'static str = "future_incompatible";
21+
1922
declare_lint! {
2023
pub CONST_ERR,
2124
Warn,
@@ -117,6 +120,13 @@ declare_lint! {
117120
Allow,
118121
"detects trivial casts of numeric types which could be removed"
119122
}
123+
124+
declare_lint! {
125+
pub MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
126+
Warn,
127+
"unit struct or enum variant erroneously allowed to match via path::ident(..)"
128+
}
129+
120130
/// Does nothing as a lint pass, but registers some `Lint`s
121131
/// which are used by other parts of the compiler.
122132
#[derive(Copy, Clone)]
@@ -141,6 +151,7 @@ impl LintPass for HardwiredLints {
141151
FAT_PTR_TRANSMUTES,
142152
TRIVIAL_CASTS,
143153
TRIVIAL_NUMERIC_CASTS,
154+
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
144155
CONST_ERR
145156
)
146157
}

src/librustc/lint/context.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,12 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
363363
/// in trans that run after the main lint pass is finished. Most
364364
/// lints elsewhere in the compiler should call
365365
/// `Session::add_lint()` instead.
366-
pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
367-
lvlsrc: LevelSource, span: Option<Span>, msg: &str) {
366+
pub fn raw_emit_lint(sess: &Session,
367+
lints: &LintStore,
368+
lint: &'static Lint,
369+
lvlsrc: LevelSource,
370+
span: Option<Span>,
371+
msg: &str) {
368372
let (mut level, source) = lvlsrc;
369373
if level == Allow { return }
370374

@@ -399,6 +403,18 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
399403
_ => sess.bug("impossible level in raw_emit_lint"),
400404
}
401405

406+
// Check for future incompatibility lints and issue a stronger warning.
407+
let future_incompat_lints = &lints.lint_groups[builtin::FUTURE_INCOMPATIBLE];
408+
let this_id = LintId::of(lint);
409+
if future_incompat_lints.0.iter().any(|&id| id == this_id) {
410+
let msg = "this lint will become a HARD ERROR in a future release!";
411+
if let Some(sp) = span {
412+
sess.span_note(sp, msg);
413+
} else {
414+
sess.note(msg);
415+
}
416+
}
417+
402418
if let Some(span) = def {
403419
sess.span_note(span, "lint level defined here");
404420
}
@@ -428,7 +444,7 @@ pub trait LintContext: Sized {
428444
Some(&pair) => pair,
429445
};
430446

431-
raw_emit_lint(&self.sess(), lint, (level, src), span, msg);
447+
raw_emit_lint(&self.sess(), self.lints(), lint, (level, src), span, msg);
432448
}
433449

434450
/// Emit a lint at the appropriate level, for a particular span.

src/librustc_lint/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
146146
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
147147
UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
148148

149+
add_lint_group!(sess, FUTURE_INCOMPATIBLE,
150+
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT);
151+
149152
// We have one lint pass defined specially
150153
store.register_late_pass(sess, false, box lint::GatherNodeLevels);
151154

src/librustc_trans/trans/base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span,
22042204
// Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
22052205
// pass for the latter already ran.
22062206
lint::raw_emit_lint(&ccx.tcx().sess,
2207+
&ccx.tcx().sess.lint_store.borrow(),
22072208
lint::builtin::VARIANT_SIZE_DIFFERENCES,
22082209
*lvlsrc.unwrap(),
22092210
Some(sp),

src/librustc_typeck/check/_match.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
1919
use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
2020
use check::{check_expr_with_lvalue_pref};
2121
use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
22+
use lint;
2223
use require_same_types;
2324
use util::nodemap::FnvHashMap;
2425
use session::Session;
@@ -138,7 +139,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
138139
if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
139140
if let hir::PatEnum(ref path, ref subpats) = pat.node {
140141
if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) {
141-
bad_struct_kind_err(tcx.sess, pat.span, path, false);
142+
bad_struct_kind_err(tcx.sess, pat, path, false);
142143
return;
143144
}
144145
}
@@ -580,10 +581,21 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
580581
}
581582

582583
// This function exists due to the warning "diagnostic code E0164 already used"
583-
fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path, is_warning: bool) {
584+
fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
584585
let name = pprust::path_to_string(path);
585-
span_err_or_warn!(is_warning, sess, span, E0164,
586-
"`{}` does not name a tuple variant or a tuple struct", name);
586+
let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
587+
if lint {
588+
let expanded_msg =
589+
format!("{}; RFC 218 disallowed matching of unit variants or unit structs via {}(..)",
590+
msg,
591+
name);
592+
sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
593+
pat.id,
594+
pat.span,
595+
expanded_msg);
596+
} else {
597+
span_err!(sess, pat.span, E0164, "{}", msg);
598+
}
587599
}
588600

589601
pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
@@ -634,11 +646,8 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
634646
opt_ty, def, pat.span, pat.id);
635647

636648
let report_bad_struct_kind = |is_warning| {
637-
bad_struct_kind_err(tcx.sess, pat.span, path, is_warning);
638-
if is_warning {
639-
return
640-
}
641-
649+
bad_struct_kind_err(tcx.sess, pat, path, is_warning);
650+
if is_warning { return; }
642651
fcx.write_error(pat.id);
643652
if let Some(subpats) = subpats {
644653
for pat in subpats {
@@ -676,10 +685,6 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
676685
report_bad_struct_kind(is_special_case);
677686
if !is_special_case {
678687
return
679-
} else {
680-
span_note!(tcx.sess, pat.span,
681-
"this warning will become a HARD ERROR in a future release. \
682-
See RFC 218 for details.");
683688
}
684689
}
685690
(variant.fields
@@ -693,7 +698,10 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
693698
ty::TyStruct(struct_def, expected_substs) => {
694699
let variant = struct_def.struct_variant();
695700
if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
696-
report_bad_struct_kind(false);
701+
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
702+
// is allowed for backward compatibility.
703+
let is_special_case = variant.kind() == ty::VariantKind::Unit;
704+
report_bad_struct_kind(is_special_case);
697705
return;
698706
}
699707
(variant.fields

src/test/compile-fail/empty-struct-unit-pat.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// Can't use unit struct as enum pattern
1212

13+
#![feature(rustc_attrs)]
14+
// remove prior feature after warning cycle and promoting warnings to errors
1315
#![feature(braced_empty_structs)]
1416

1517
struct Empty1;
@@ -18,7 +20,9 @@ enum E {
1820
Empty2
1921
}
2022

21-
fn main() {
23+
// remove attribute after warning cycle and promoting warnings to errors
24+
#[rustc_error]
25+
fn main() { //~ ERROR: compilation successful
2226
let e1 = Empty1;
2327
let e2 = E::Empty2;
2428

@@ -27,7 +31,7 @@ fn main() {
2731
// Empty1() => () // ERROR `Empty1` does not name a tuple variant or a tuple struct
2832
// }
2933
match e1 {
30-
Empty1(..) => () //~ ERROR `Empty1` does not name a tuple variant or a tuple struct
34+
Empty1(..) => () //~ WARN `Empty1` does not name a tuple variant or a tuple struct
3135
}
3236
// Rejected by parser as yet
3337
// match e2 {

src/test/compile-fail/match-pattern-field-mismatch-2.rs

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ fn main() {
2121
color::cmyk(_, _, _, _) => { }
2222
color::no_color(_) => { }
2323
//~^ ERROR this pattern has 1 field, but the corresponding variant has no fields
24-
//~^^ WARN `color::no_color` does not name a tuple variant or a tuple struct
2524
}
2625
}
2726
}

src/test/compile-fail/pattern-error-continue.rs

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ fn main() {
2626
match A::B(1, 2) {
2727
A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
2828
A::D(_) => (), //~ ERROR this pattern has 1 field, but
29-
//~^ WARN `A::D` does not name a tuple variant or a tuple struct
3029
_ => ()
3130
}
3231
match 'c' {

0 commit comments

Comments
 (0)