Skip to content

Commit

Permalink
Auto merge of rust-lang#120242 - matthiaskrgr:rollup-a93yj3i, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 10 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#120218 (rustfmt: Check that a token can begin a nonterminal kind before parsing it as a macro arg)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 22, 2024
2 parents 021861a + 0b0f0be commit d5fd099
Show file tree
Hide file tree
Showing 31 changed files with 556 additions and 226 deletions.
62 changes: 61 additions & 1 deletion compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,67 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
}
match rvalue {
Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
Rvalue::Aggregate(kind, fields) => match **kind {
AggregateKind::Tuple => {}
AggregateKind::Array(dest) => {
for src in fields {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
self.fail(location, "array field has the wrong type");
}
}
}
AggregateKind::Adt(def_id, idx, args, _, Some(field)) => {
let adt_def = self.tcx.adt_def(def_id);
assert!(adt_def.is_union());
assert_eq!(idx, FIRST_VARIANT);
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
if fields.len() != 1 {
self.fail(location, "unions should have one initialized field");
}
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
self.fail(location, "union field has the wrong type");
}
}
AggregateKind::Adt(def_id, idx, args, _, None) => {
let adt_def = self.tcx.adt_def(def_id);
assert!(!adt_def.is_union());
let variant = &adt_def.variants()[idx];
if variant.fields.len() != fields.len() {
self.fail(location, "adt has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, &variant.fields) {
if !self.mir_assign_valid_types(
src.ty(self.body, self.tcx),
dest.ty(self.tcx, args),
) {
self.fail(location, "adt field has the wrong type");
}
}
}
AggregateKind::Closure(_, args) => {
let upvars = args.as_closure().upvar_tys();
if upvars.len() != fields.len() {
self.fail(location, "closure has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
self.fail(location, "closure field has the wrong type");
}
}
}
AggregateKind::Coroutine(_, args) => {
let upvars = args.as_coroutine().upvar_tys();
if upvars.len() != fields.len() {
self.fail(location, "coroutine has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
self.fail(location, "coroutine field has the wrong type");
}
}
}
},
Rvalue::Ref(_, BorrowKind::Fake, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_hir_analysis/src/astconv/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return false;
};
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
let mut is_downgradable = true;
let is_object_safe = match self_ty.kind {
hir::TyKind::TraitObject(objects, ..) => {
objects.iter().all(|o| match o.trait_ref.path.res {
Res::Def(DefKind::Trait, id) if Some(id) == owner => {
// When we're dealing with a recursive trait, we don't want to downgrade
// the error, so we consider them to be object safe always. (#119652)
true
Res::Def(DefKind::Trait, id) => {
if Some(id) == owner {
// For recursive traits, don't downgrade the error. (#119652)
is_downgradable = false;
}
tcx.check_is_object_safe(id)
}
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
_ => false,
})
}
Expand Down Expand Up @@ -130,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
],
Applicability::MachineApplicable,
);
} else if diag.is_error() {
} else if diag.is_error() && is_downgradable {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
Expand All @@ -156,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if !is_object_safe {
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
if diag.is_error() {
if diag.is_error() && is_downgradable {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
Expand Down
34 changes: 10 additions & 24 deletions compiler/rustc_infer/src/infer/relate/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
//
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
let compatible_types = self.probe(|_| {
self.probe(|_| {
if a.ty() == b.ty() {
return Ok(());
return;
}

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

// If the consts have differing types, just bail with a const error with
// the expected const's type. Specifically, we don't want const infer vars
// to do any type shapeshifting before and after resolution.
if let Err(guar) = compatible_types {
// HACK: equating both sides with `[const error]` eagerly prevents us
// from leaving unconstrained inference vars during things like impl
// matching in the solver.
let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
return self.unify_const_variable(vid, a_error, relation.param_env());
}
let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
return self.unify_const_variable(vid, b_error, relation.param_env());
}

return Ok(if relation.a_is_expected() { a_error } else { b_error });
}

match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.
// We want to be able to build this crate with a stable compiler,
// so no `#![feature]` attributes should be added.
#![deny(unstable_features)]

mod cursor;
pub mod unescape;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ lint_builtin_unsafe_impl = implementation of an `unsafe` trait
lint_builtin_unsafe_trait = declaration of an `unsafe` trait
lint_builtin_unstable_features = unstable feature
lint_builtin_unstable_features = use of an unstable feature
lint_builtin_unused_doc_comment = unused doc comment
.label = rustdoc does not generate documentation for {$kind}
Expand Down
34 changes: 27 additions & 7 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1233,10 +1233,30 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
}

declare_lint! {
/// The `unstable_features` is deprecated and should no longer be used.
/// The `unstable_features` lint detects uses of `#![feature]`.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(unstable_features)]
/// #![feature(test)]
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// In larger nightly-based projects which
///
/// * consist of a multitude of crates where a subset of crates has to compile on
/// stable either unconditionally or depending on a `cfg` flag to for example
/// allow stable users to depend on them,
/// * don't use nightly for experimental features but for, e.g., unstable options only,
///
/// this lint may come in handy to enforce policies of these kinds.
UNSTABLE_FEATURES,
Allow,
"enabling unstable features (deprecated. do not use)"
"enabling unstable features"
}

declare_lint_pass!(
Expand All @@ -1246,11 +1266,11 @@ declare_lint_pass!(

impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
if attr.has_name(sym::feature) {
if let Some(items) = attr.meta_item_list() {
for item in items {
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
}
if attr.has_name(sym::feature)
&& let Some(items) = attr.meta_item_list()
{
for item in items {
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
}
}
}
Expand Down
88 changes: 49 additions & 39 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use rustc_pattern_analysis::errors::Uncovered;
use rustc_pattern_analysis::rustc::{
Constructor, DeconstructedPat, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
UsefulnessReport, WitnessPat,
};
use rustc_pattern_analysis::{analyze_match, MatchArm};

use crate::errors::*;

Expand Down Expand Up @@ -390,6 +389,34 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
}
}

fn analyze_patterns(
&mut self,
cx: &MatchCheckCtxt<'p, 'tcx>,
arms: &[MatchArm<'p, 'tcx>],
scrut_ty: Ty<'tcx>,
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
let report =
rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
self.error = Err(err);
err
})?;

// Warn unreachable subpatterns.
for (arm, is_useful) in report.arm_usefulness.iter() {
if let Usefulness::Useful(redundant_subpats) = is_useful
&& !redundant_subpats.is_empty()
{
let mut redundant_subpats = redundant_subpats.clone();
// Emit lints in the order in which they occur in the file.
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
for pat in redundant_subpats {
report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None)
}
}
}
Ok(report)
}

#[instrument(level = "trace", skip(self))]
fn check_let(&mut self, pat: &'p Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) {
assert!(self.let_source != LetSource::None);
Expand Down Expand Up @@ -435,14 +462,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
}
}

let scrut_ty = scrut.ty;
let report = match analyze_match(&cx, &tarms, scrut_ty) {
Ok(report) => report,
Err(err) => {
self.error = Err(err);
return;
}
};
let Ok(report) = self.analyze_patterns(&cx, &tarms, scrut.ty) else { return };

match source {
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
Expand Down Expand Up @@ -474,7 +494,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
);
} else {
self.error = Err(report_non_exhaustive_match(
&cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
&cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span,
));
}
}
Expand Down Expand Up @@ -556,7 +576,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
let cx = self.new_cx(refutability, None, scrut, pat.span);
let pat = self.lower_pattern(&cx, pat)?;
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
let report = analyze_match(&cx, &arms, pat.ty().inner())?;
let report = self.analyze_patterns(&cx, &arms, pat.ty().inner())?;
Ok((cx, report))
}

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

/// Report unreachable arms, if any.
fn report_unreachable_pattern<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>,
hir_id: HirId,
span: Span,
catchall: Option<Span>,
) {
cx.tcx.emit_spanned_lint(
UNREACHABLE_PATTERNS,
hir_id,
span,
UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
);
}

/// Report unreachable arms, if any.
fn report_arm_reachability<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>,
report: &UsefulnessReport<'p, 'tcx>,
) {
let report_unreachable_pattern = |span, hir_id, catchall: Option<Span>| {
cx.tcx.emit_spanned_lint(
UNREACHABLE_PATTERNS,
hir_id,
span,
UnreachablePattern {
span: if catchall.is_some() { Some(span) } else { None },
catchall,
},
);
};

let mut catchall = None;
for (arm, is_useful) in report.arm_usefulness.iter() {
match is_useful {
Usefulness::Redundant => {
report_unreachable_pattern(arm.pat.data().unwrap().span, arm.arm_data, catchall)
}
Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {}
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
Usefulness::Useful(redundant_subpats) => {
let mut redundant_subpats = redundant_subpats.clone();
// Emit lints in the order in which they occur in the file.
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
for pat in redundant_subpats {
report_unreachable_pattern(pat.data().unwrap().span, arm.arm_data, None);
}
}
if matches!(is_useful, Usefulness::Redundant) {
report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall)
}
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
catchall = Some(arm.pat.data().unwrap().span);
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
// WARNING: We want to be able to build this crate with a stable compiler,
// so no `#![feature]` attributes should be added!
// We want to be able to build this crate with a stable compiler,
// so no `#![feature]` attributes should be added.
#![deny(unstable_features)]

use rustc_lexer::unescape;
pub use Alignment::*;
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1924,7 +1924,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {

// Free the allocation without dropping its contents
let (bptr, alloc) = Box::into_raw_with_allocator(src);
let src = Box::from_raw(bptr as *mut mem::ManuallyDrop<T>);
let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop<T>, alloc.by_ref());
drop(src);

Self::from_ptr_in(ptr, alloc)
Expand Down
Loading

0 comments on commit d5fd099

Please sign in to comment.