Skip to content

Commit dbeb3ba

Browse files
committed
Auto merge of rust-lang#120237 - matthiaskrgr:rollup-yn3hf5u, r=matthiaskrgr
Rollup of 11 pull requests Successful merges: - rust-lang#117910 (Refactor uses of `objc_msgSend` to no longer have clashing definitions) - rust-lang#118639 (Undeprecate lint `unstable_features` and make use of it in the compiler) - rust-lang#119801 (Fix deallocation with wrong allocator in (A)Rc::from_box_in) - rust-lang#120058 (bootstrap: improvements for compiler builds) - rust-lang#120059 (Make generic const type mismatches not hide trait impls from the trait solver) - rust-lang#120097 (Report unreachable subpatterns consistently) - rust-lang#120137 (Validate AggregateKind types in MIR) - rust-lang#120164 (`maybe_lint_impl_trait`: separate `is_downgradable` from `is_object_safe`) - rust-lang#120181 (Allow any `const` expression blocks in `thread_local!`) - rust-lang#120204 (Builtin macros effectively have implicit #[collapse_debuginfo(yes)]) - rust-lang#120218 (rustfmt: Check that a token can begin a nonterminal kind before parsing it as a macro arg) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3066253 + e153296 commit dbeb3ba

File tree

33 files changed

+595
-227
lines changed

33 files changed

+595
-227
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

+61-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,67 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
796796
};
797797
}
798798
match rvalue {
799-
Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
799+
Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
800+
Rvalue::Aggregate(kind, fields) => match **kind {
801+
AggregateKind::Tuple => {}
802+
AggregateKind::Array(dest) => {
803+
for src in fields {
804+
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
805+
self.fail(location, "array field has the wrong type");
806+
}
807+
}
808+
}
809+
AggregateKind::Adt(def_id, idx, args, _, Some(field)) => {
810+
let adt_def = self.tcx.adt_def(def_id);
811+
assert!(adt_def.is_union());
812+
assert_eq!(idx, FIRST_VARIANT);
813+
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
814+
if fields.len() != 1 {
815+
self.fail(location, "unions should have one initialized field");
816+
}
817+
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
818+
self.fail(location, "union field has the wrong type");
819+
}
820+
}
821+
AggregateKind::Adt(def_id, idx, args, _, None) => {
822+
let adt_def = self.tcx.adt_def(def_id);
823+
assert!(!adt_def.is_union());
824+
let variant = &adt_def.variants()[idx];
825+
if variant.fields.len() != fields.len() {
826+
self.fail(location, "adt has the wrong number of initialized fields");
827+
}
828+
for (src, dest) in std::iter::zip(fields, &variant.fields) {
829+
if !self.mir_assign_valid_types(
830+
src.ty(self.body, self.tcx),
831+
dest.ty(self.tcx, args),
832+
) {
833+
self.fail(location, "adt field has the wrong type");
834+
}
835+
}
836+
}
837+
AggregateKind::Closure(_, args) => {
838+
let upvars = args.as_closure().upvar_tys();
839+
if upvars.len() != fields.len() {
840+
self.fail(location, "closure has the wrong number of initialized fields");
841+
}
842+
for (src, dest) in std::iter::zip(fields, upvars) {
843+
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
844+
self.fail(location, "closure field has the wrong type");
845+
}
846+
}
847+
}
848+
AggregateKind::Coroutine(_, args) => {
849+
let upvars = args.as_coroutine().upvar_tys();
850+
if upvars.len() != fields.len() {
851+
self.fail(location, "coroutine has the wrong number of initialized fields");
852+
}
853+
for (src, dest) in std::iter::zip(fields, upvars) {
854+
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
855+
self.fail(location, "coroutine field has the wrong type");
856+
}
857+
}
858+
}
859+
},
800860
Rvalue::Ref(_, BorrowKind::Fake, _) => {
801861
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
802862
self.fail(

compiler/rustc_expand/src/base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,15 @@ impl SyntaxExtension {
796796
/// | external | no | if-ext | if-ext | yes |
797797
/// | yes | yes | yes | yes | yes |
798798
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
799-
let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
799+
let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
800800
.map(|v| Self::collapse_debuginfo_by_name(sess, v))
801801
.unwrap_or(CollapseMacroDebuginfo::Unspecified);
802+
if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
803+
&& attr::contains_name(attrs, sym::rustc_builtin_macro)
804+
{
805+
collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
806+
}
807+
802808
let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
803809
let attr = collapse_debuginfo_attr;
804810
let ext = !is_local;

compiler/rustc_hir_analysis/src/astconv/lint.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9494
return false;
9595
};
9696
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
97+
let mut is_downgradable = true;
9798
let is_object_safe = match self_ty.kind {
9899
hir::TyKind::TraitObject(objects, ..) => {
99100
objects.iter().all(|o| match o.trait_ref.path.res {
100-
Res::Def(DefKind::Trait, id) if Some(id) == owner => {
101-
// When we're dealing with a recursive trait, we don't want to downgrade
102-
// the error, so we consider them to be object safe always. (#119652)
103-
true
101+
Res::Def(DefKind::Trait, id) => {
102+
if Some(id) == owner {
103+
// For recursive traits, don't downgrade the error. (#119652)
104+
is_downgradable = false;
105+
}
106+
tcx.check_is_object_safe(id)
104107
}
105-
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
106108
_ => false,
107109
})
108110
}
@@ -130,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
130132
],
131133
Applicability::MachineApplicable,
132134
);
133-
} else if diag.is_error() {
135+
} else if diag.is_error() && is_downgradable {
134136
// We'll emit the object safety error already, with a structured suggestion.
135137
diag.downgrade_to_delayed_bug();
136138
}
@@ -156,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
156158
}
157159
if !is_object_safe {
158160
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
159-
if diag.is_error() {
161+
if diag.is_error() && is_downgradable {
160162
// We'll emit the object safety error already, with a structured suggestion.
161163
diag.downgrade_to_delayed_bug();
162164
}

compiler/rustc_infer/src/infer/relate/combine.rs

+10-24
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
165165
//
166166
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
167167
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
168-
let compatible_types = self.probe(|_| {
168+
self.probe(|_| {
169169
if a.ty() == b.ty() {
170-
return Ok(());
170+
return;
171171
}
172172

173173
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
@@ -177,32 +177,18 @@ impl<'tcx> InferCtxt<'tcx> {
177177
relation.param_env().and((a.ty(), b.ty())),
178178
&mut OriginalQueryValues::default(),
179179
);
180-
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
180+
self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
181+
// The error will only be reported later. If we emit an ErrorGuaranteed
182+
// here, then we will never get to the code that actually emits the error.
181183
self.tcx.dcx().delayed_bug(format!(
182184
"cannot relate consts of different types (a={a:?}, b={b:?})",
183-
))
184-
})
185+
));
186+
// We treat these constants as if they were of the same type, so that any
187+
// such constants being used in impls make these impls match barring other mismatches.
188+
// This helps with diagnostics down the road.
189+
});
185190
});
186191

187-
// If the consts have differing types, just bail with a const error with
188-
// the expected const's type. Specifically, we don't want const infer vars
189-
// to do any type shapeshifting before and after resolution.
190-
if let Err(guar) = compatible_types {
191-
// HACK: equating both sides with `[const error]` eagerly prevents us
192-
// from leaving unconstrained inference vars during things like impl
193-
// matching in the solver.
194-
let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
195-
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
196-
return self.unify_const_variable(vid, a_error, relation.param_env());
197-
}
198-
let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
199-
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
200-
return self.unify_const_variable(vid, b_error, relation.param_env());
201-
}
202-
203-
return Ok(if relation.a_is_expected() { a_error } else { b_error });
204-
}
205-
206192
match (a.kind(), b.kind()) {
207193
(
208194
ty::ConstKind::Infer(InferConst::Var(a_vid)),

compiler/rustc_lexer/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
2121
#![deny(rustc::untranslatable_diagnostic)]
2222
#![deny(rustc::diagnostic_outside_of_impl)]
23-
// We want to be able to build this crate with a stable compiler, so no
24-
// `#![feature]` attributes should be added.
23+
// We want to be able to build this crate with a stable compiler,
24+
// so no `#![feature]` attributes should be added.
25+
#![deny(unstable_features)]
2526

2627
mod cursor;
2728
pub mod unescape;

compiler/rustc_lint/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ lint_builtin_unsafe_impl = implementation of an `unsafe` trait
148148
149149
lint_builtin_unsafe_trait = declaration of an `unsafe` trait
150150
151-
lint_builtin_unstable_features = unstable feature
151+
lint_builtin_unstable_features = use of an unstable feature
152152
153153
lint_builtin_unused_doc_comment = unused doc comment
154154
.label = rustdoc does not generate documentation for {$kind}

compiler/rustc_lint/src/builtin.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -1233,10 +1233,30 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
12331233
}
12341234

12351235
declare_lint! {
1236-
/// The `unstable_features` is deprecated and should no longer be used.
1236+
/// The `unstable_features` lint detects uses of `#![feature]`.
1237+
///
1238+
/// ### Example
1239+
///
1240+
/// ```rust,compile_fail
1241+
/// #![deny(unstable_features)]
1242+
/// #![feature(test)]
1243+
/// ```
1244+
///
1245+
/// {{produces}}
1246+
///
1247+
/// ### Explanation
1248+
///
1249+
/// In larger nightly-based projects which
1250+
///
1251+
/// * consist of a multitude of crates where a subset of crates has to compile on
1252+
/// stable either unconditionally or depending on a `cfg` flag to for example
1253+
/// allow stable users to depend on them,
1254+
/// * don't use nightly for experimental features but for, e.g., unstable options only,
1255+
///
1256+
/// this lint may come in handy to enforce policies of these kinds.
12371257
UNSTABLE_FEATURES,
12381258
Allow,
1239-
"enabling unstable features (deprecated. do not use)"
1259+
"enabling unstable features"
12401260
}
12411261

12421262
declare_lint_pass!(
@@ -1246,11 +1266,11 @@ declare_lint_pass!(
12461266

12471267
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
12481268
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
1249-
if attr.has_name(sym::feature) {
1250-
if let Some(items) = attr.meta_item_list() {
1251-
for item in items {
1252-
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
1253-
}
1269+
if attr.has_name(sym::feature)
1270+
&& let Some(items) = attr.meta_item_list()
1271+
{
1272+
for item in items {
1273+
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
12541274
}
12551275
}
12561276
}

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+49-39
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use rustc_pattern_analysis::errors::Uncovered;
22
use rustc_pattern_analysis::rustc::{
3-
Constructor, DeconstructedPat, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
3+
Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
44
UsefulnessReport, WitnessPat,
55
};
6-
use rustc_pattern_analysis::{analyze_match, MatchArm};
76

87
use crate::errors::*;
98

@@ -390,6 +389,34 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
390389
}
391390
}
392391

392+
fn analyze_patterns(
393+
&mut self,
394+
cx: &MatchCheckCtxt<'p, 'tcx>,
395+
arms: &[MatchArm<'p, 'tcx>],
396+
scrut_ty: Ty<'tcx>,
397+
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
398+
let report =
399+
rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
400+
self.error = Err(err);
401+
err
402+
})?;
403+
404+
// Warn unreachable subpatterns.
405+
for (arm, is_useful) in report.arm_usefulness.iter() {
406+
if let Usefulness::Useful(redundant_subpats) = is_useful
407+
&& !redundant_subpats.is_empty()
408+
{
409+
let mut redundant_subpats = redundant_subpats.clone();
410+
// Emit lints in the order in which they occur in the file.
411+
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
412+
for pat in redundant_subpats {
413+
report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None)
414+
}
415+
}
416+
}
417+
Ok(report)
418+
}
419+
393420
#[instrument(level = "trace", skip(self))]
394421
fn check_let(&mut self, pat: &'p Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) {
395422
assert!(self.let_source != LetSource::None);
@@ -435,14 +462,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
435462
}
436463
}
437464

438-
let scrut_ty = scrut.ty;
439-
let report = match analyze_match(&cx, &tarms, scrut_ty) {
440-
Ok(report) => report,
441-
Err(err) => {
442-
self.error = Err(err);
443-
return;
444-
}
445-
};
465+
let Ok(report) = self.analyze_patterns(&cx, &tarms, scrut.ty) else { return };
446466

447467
match source {
448468
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
@@ -474,7 +494,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
474494
);
475495
} else {
476496
self.error = Err(report_non_exhaustive_match(
477-
&cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
497+
&cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span,
478498
));
479499
}
480500
}
@@ -556,7 +576,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
556576
let cx = self.new_cx(refutability, None, scrut, pat.span);
557577
let pat = self.lower_pattern(&cx, pat)?;
558578
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
559-
let report = analyze_match(&cx, &arms, pat.ty().inner())?;
579+
let report = self.analyze_patterns(&cx, &arms, pat.ty().inner())?;
560580
Ok((cx, report))
561581
}
562582

@@ -567,7 +587,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
567587
) -> Result<RefutableFlag, ErrorGuaranteed> {
568588
let (cx, report) = self.analyze_binding(pat, Refutable, scrut)?;
569589
// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
570-
// This also reports unreachable sub-patterns.
571590
report_arm_reachability(&cx, &report);
572591
// If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
573592
// irrefutable.
@@ -850,39 +869,30 @@ fn report_irrefutable_let_patterns(
850869
}
851870
}
852871

872+
/// Report unreachable arms, if any.
873+
fn report_unreachable_pattern<'p, 'tcx>(
874+
cx: &MatchCheckCtxt<'p, 'tcx>,
875+
hir_id: HirId,
876+
span: Span,
877+
catchall: Option<Span>,
878+
) {
879+
cx.tcx.emit_spanned_lint(
880+
UNREACHABLE_PATTERNS,
881+
hir_id,
882+
span,
883+
UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
884+
);
885+
}
886+
853887
/// Report unreachable arms, if any.
854888
fn report_arm_reachability<'p, 'tcx>(
855889
cx: &MatchCheckCtxt<'p, 'tcx>,
856890
report: &UsefulnessReport<'p, 'tcx>,
857891
) {
858-
let report_unreachable_pattern = |span, hir_id, catchall: Option<Span>| {
859-
cx.tcx.emit_spanned_lint(
860-
UNREACHABLE_PATTERNS,
861-
hir_id,
862-
span,
863-
UnreachablePattern {
864-
span: if catchall.is_some() { Some(span) } else { None },
865-
catchall,
866-
},
867-
);
868-
};
869-
870892
let mut catchall = None;
871893
for (arm, is_useful) in report.arm_usefulness.iter() {
872-
match is_useful {
873-
Usefulness::Redundant => {
874-
report_unreachable_pattern(arm.pat.data().unwrap().span, arm.arm_data, catchall)
875-
}
876-
Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {}
877-
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
878-
Usefulness::Useful(redundant_subpats) => {
879-
let mut redundant_subpats = redundant_subpats.clone();
880-
// Emit lints in the order in which they occur in the file.
881-
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
882-
for pat in redundant_subpats {
883-
report_unreachable_pattern(pat.data().unwrap().span, arm.arm_data, None);
884-
}
885-
}
894+
if matches!(is_useful, Usefulness::Redundant) {
895+
report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall)
886896
}
887897
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
888898
catchall = Some(arm.pat.data().unwrap().span);

0 commit comments

Comments
 (0)