about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_region.rs427
-rw-r--r--compiler/rustc_infer/src/infer/note.rs203
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs63
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs98
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs6
-rw-r--r--library/alloc/src/collections/btree/mod.rs3
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs4
-rw-r--r--library/alloc/src/collections/linked_list/tests.rs56
-rw-r--r--library/alloc/src/lib.rs4
-rw-r--r--library/alloc/src/testing/crash_test.rs (renamed from library/alloc/src/collections/btree/testing/crash_test.rs)0
-rw-r--r--library/alloc/src/testing/mod.rs (renamed from library/alloc/src/collections/btree/testing/mod.rs)0
-rw-r--r--library/alloc/src/testing/ord_chaos.rs (renamed from library/alloc/src/collections/btree/testing/ord_chaos.rs)0
-rw-r--r--library/alloc/src/testing/rng.rs (renamed from library/alloc/src/collections/btree/testing/rng.rs)0
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/error.rs1
-rw-r--r--library/core/src/iter/sources/empty.rs7
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/std/src/sync/mpmc/utils.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr57
-rw-r--r--src/test/ui/lint/unused/must-use-box-from-raw.stderr2
-rw-r--r--src/test/ui/match/single-line.rs3
-rw-r--r--src/test/ui/match/single-line.stderr12
-rw-r--r--src/test/ui/repr/transparent-enum-too-many-variants.rs10
-rw-r--r--src/test/ui/repr/transparent-enum-too-many-variants.stderr11
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs10
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr14
33 files changed, 321 insertions, 706 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a616dd70f8e..060306d88be 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -160,6 +160,8 @@ declare_features! (
     (active, intrinsics, "1.0.0", None, None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (active, lang_items, "1.0.0", None, None),
+    /// Allows the `multiple_supertrait_upcastable` lint.
+    (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a714663741b..87cc69757b0 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1060,10 +1060,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
 
     if adt.variants().len() != 1 {
         bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
-        if adt.variants().is_empty() {
-            // Don't bother checking the fields. No variants (and thus no fields) exist.
-            return;
-        }
+        // Don't bother checking the fields.
+        return;
     }
 
     // For each field, figure out if it's known to be a ZST and align(1), with "known"
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 96a976fb89e..e5823660e3f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -729,7 +729,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             format!("this and all prior arms are found to be of type `{}`", t),
                         );
                     }
-                    let outer_error_span = if any_multiline_arm {
+                    let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) {
                         // Cover just `match` and the scrutinee expression, not
                         // the entire match body, to reduce diagram noise.
                         cause.span.shrink_to_lo().to(scrut_span)
@@ -737,7 +737,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         cause.span
                     };
                     let msg = "`match` arms have incompatible types";
-                    err.span_label(outer_error_span, msg);
+                    err.span_label(outer, msg);
                     self.suggest_remove_semi_or_return_binding(
                         err,
                         prior_arm_block_id,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
deleted file mode 100644
index 41b115f3377..00000000000
--- a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
+++ /dev/null
@@ -1,427 +0,0 @@
-use crate::errors::RegionOriginNote;
-use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
-use crate::infer::{self, SubregionOrigin};
-use rustc_errors::{
-    fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-};
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, Region};
-
-use super::ObligationCauseAsDiagArg;
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
-        match *origin {
-            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
-                span: trace.cause.span,
-                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values),
-            }
-            .add_to_diagnostic(err),
-            infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
-            }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reborrow,
-                    name: &var_name.to_string(),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
-                    .add_to_diagnostic(err);
-            }
-            infer::DataBorrowed(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_data_borrowed,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reference_outlives_referent,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_relate_param_bound,
-                    name: &self.ty_to_string(ty),
-                    continues: opt_span.is_some(),
-                }
-                .add_to_diagnostic(err);
-                if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diagnostic(err);
-                }
-            }
-            infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diagnostic(err);
-            }
-            infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diagnostic(err);
-            }
-            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
-                self.note_region_origin(err, &parent);
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                RegionOriginNote::Plain {
-                    span,
-                    msg: fluent::infer_ascribe_user_type_prove_predicate,
-                }
-                .add_to_diagnostic(err);
-            }
-        }
-    }
-
-    pub(super) fn report_concrete_failure(
-        &self,
-        origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        match origin {
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
-                let mut err = self.report_and_explain_type_error(trace, terr);
-                match (*sub, *sup) {
-                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
-                    (ty::RePlaceholder(_), _) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "",
-                            sup,
-                            " doesn't meet the lifetime requirements",
-                            None,
-                        );
-                    }
-                    (_, ty::RePlaceholder(_)) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "the required lifetime does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                    _ => {
-                        note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "...does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                }
-                err
-            }
-            infer::Reborrow(span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0312,
-                    "lifetime of reference outlives lifetime of borrowed content..."
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...the reference is valid for ",
-                    sub,
-                    "...",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...but the borrowed content is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0313,
-                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
-                    var_name
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...the borrowed pointer is valid for ",
-                    sub,
-                    "...",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    &format!("...but `{}` is only valid for ", var_name),
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::RelateObjectBound(span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0476,
-                    "lifetime of the source pointer does not outlive lifetime bound of the \
-                     object type"
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "object type is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "source pointer is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0477,
-                    "the type `{}` does not fulfill the required lifetime",
-                    self.ty_to_string(ty)
-                );
-                match *sub {
-                    ty::ReStatic => note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "type must satisfy ",
-                        sub,
-                        if opt_span.is_some() { " as required by this binding" } else { "" },
-                        opt_span,
-                    ),
-                    _ => note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "type must outlive ",
-                        sub,
-                        if opt_span.is_some() { " as required by this binding" } else { "" },
-                        opt_span,
-                    ),
-                }
-                err
-            }
-            infer::RelateRegionParamBound(span) => {
-                let mut err =
-                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "lifetime parameter instantiated with ",
-                    sup,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but lifetime parameter must outlive ",
-                    sub,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::DataBorrowed(ty, span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0490,
-                    "a value of type `{}` is borrowed for too long",
-                    self.ty_to_string(ty)
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "the type is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but the borrow lasts for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0491,
-                    "in type `{}`, reference has a longer lifetime than the data it references",
-                    self.ty_to_string(ty)
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "the pointer is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but the referenced data is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
-                .report_extra_impl_obligation(
-                    span,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    &format!("`{}: {}`", sup, sub),
-                ),
-            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
-                let mut err = self.report_concrete_failure(*parent, sub, sup);
-
-                let trait_item_span = self.tcx.def_span(trait_item_def_id);
-                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                err.span_label(
-                    trait_item_span,
-                    format!("definition of `{}` from trait", item_name),
-                );
-
-                let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
-                let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
-
-                let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
-                    impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
-                let clauses: Vec<_> = trait_predicates
-                    .predicates
-                    .into_iter()
-                    .filter(|&(pred, _)| !impl_predicates.contains(pred))
-                    .map(|(pred, _)| format!("{}", pred))
-                    .collect();
-
-                if !clauses.is_empty() {
-                    let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
-                    let where_clause_span = generics.tail_span_for_predicate_suggestion();
-
-                    let suggestion = format!(
-                        "{} {}",
-                        generics.add_where_or_trailing_comma(),
-                        clauses.join(", "),
-                    );
-                    err.span_suggestion(
-                        where_clause_span,
-                        &format!(
-                            "try copying {} from the trait",
-                            if clauses.len() > 1 { "these clauses" } else { "this clause" }
-                        ),
-                        suggestion,
-                        rustc_errors::Applicability::MaybeIncorrect,
-                    );
-                }
-
-                err
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                let mut err =
-                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "lifetime instantiated with ",
-                    sup,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but lifetime must outlive ",
-                    sub,
-                    "",
-                    None,
-                );
-                err
-            }
-        }
-    }
-
-    pub(super) fn report_placeholder_failure(
-        &self,
-        placeholder_origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        // I can't think how to do better than this right now. -nikomatsakis
-        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
-        match placeholder_origin {
-            infer::Subtype(box ref trace)
-                if matches!(
-                    &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::BindingObligation(..)
-                        | ObligationCauseCode::ExprBindingObligation(..)
-                ) =>
-            {
-                // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
-                    &trace.cause.code().peel_derives()
-                {
-                    let span = *span;
-                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
-                    err.span_note(span, "the lifetime requirement is introduced here");
-                    err
-                } else {
-                    unreachable!()
-                }
-            }
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsPlaceholderMismatch;
-                return self.report_and_explain_type_error(trace, terr);
-            }
-            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs
deleted file mode 100644
index 2ccbd164faa..00000000000
--- a/compiler/rustc_infer/src/infer/note.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    fn note_error_origin(
-        &self,
-        err: &mut Diagnostic,
-        cause: &ObligationCause<'tcx>,
-        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
-        terr: TypeError<'tcx>,
-    ) {
-        match *cause.code() {
-            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
-                let ty = self.resolve_vars_if_possible(root_ty);
-                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
-                {
-                    // don't show type `_`
-                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-                        && let ty::Adt(def, substs) = ty.kind()
-                        && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
-                    {
-                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
-                    } else {
-                    err.span_label(span, format!("this expression has type `{}`", ty));
-                }
-                }
-                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
-                    && ty.is_box() && ty.boxed_ty() == found
-                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-                {
-                    err.span_suggestion(
-                        span,
-                        "consider dereferencing the boxed value",
-                        format!("*{}", snippet),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
-                err.span_label(span, "expected due to this");
-            }
-            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                arm_block_id,
-                arm_span,
-                arm_ty,
-                prior_arm_block_id,
-                prior_arm_span,
-                prior_arm_ty,
-                source,
-                ref prior_arms,
-                scrut_hir_id,
-                opt_suggest_box_span,
-                scrut_span,
-                ..
-            }) => match source {
-                hir::MatchSource::TryDesugar => {
-                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
-                        let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
-                            let arg_expr = args.first().expect("try desugaring call w/out arg");
-                            self.typeck_results.as_ref().and_then(|typeck_results| {
-                                typeck_results.expr_ty_opt(arg_expr)
-                            })
-                        } else {
-                            bug!("try desugaring w/out call expr as scrutinee");
-                        };
-
-                        match scrut_ty {
-                            Some(ty) if expected == ty => {
-                                let source_map = self.tcx.sess.source_map();
-                                err.span_suggestion(
-                                    source_map.end_point(cause.span),
-                                    "try removing this `?`",
-                                    "",
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                            _ => {}
-                        }
-                    }
-                }
-                _ => {
-                    // `prior_arm_ty` can be `!`, `expected` will have better info when present.
-                    let t = self.resolve_vars_if_possible(match exp_found {
-                        Some(ty::error::ExpectedFound { expected, .. }) => expected,
-                        _ => prior_arm_ty,
-                    });
-                    let source_map = self.tcx.sess.source_map();
-                    let mut any_multiline_arm = source_map.is_multiline(arm_span);
-                    if prior_arms.len() <= 4 {
-                        for sp in prior_arms {
-                            any_multiline_arm |= source_map.is_multiline(*sp);
-                            err.span_label(*sp, format!("this is found to be of type `{}`", t));
-                        }
-                    } else if let Some(sp) = prior_arms.last() {
-                        any_multiline_arm |= source_map.is_multiline(*sp);
-                        err.span_label(
-                            *sp,
-                            format!("this and all prior arms are found to be of type `{}`", t),
-                        );
-                    }
-                    let outer_error_span = if any_multiline_arm {
-                        // Cover just `match` and the scrutinee expression, not
-                        // the entire match body, to reduce diagram noise.
-                        cause.span.shrink_to_lo().to(scrut_span)
-                    } else {
-                        cause.span
-                    };
-                    let msg = "`match` arms have incompatible types";
-                    err.span_label(outer_error_span, msg);
-                    self.suggest_remove_semi_or_return_binding(
-                        err,
-                        prior_arm_block_id,
-                        prior_arm_ty,
-                        prior_arm_span,
-                        arm_block_id,
-                        arm_ty,
-                        arm_span,
-                    );
-                    if let Some(ret_sp) = opt_suggest_box_span {
-                        // Get return type span and point to it.
-                        self.suggest_boxing_for_return_impl_trait(
-                            err,
-                            ret_sp,
-                            prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
-                        );
-                    }
-                }
-            },
-            ObligationCauseCode::IfExpression(box IfExpressionCause {
-                then_id,
-                else_id,
-                then_ty,
-                else_ty,
-                outer_span,
-                opt_suggest_box_span,
-            }) => {
-                let then_span = self.find_block_span_from_hir_id(then_id);
-                let else_span = self.find_block_span_from_hir_id(else_id);
-                err.span_label(then_span, "expected because of this");
-                if let Some(sp) = outer_span {
-                    err.span_label(sp, "`if` and `else` have incompatible types");
-                }
-                self.suggest_remove_semi_or_return_binding(
-                    err,
-                    Some(then_id),
-                    then_ty,
-                    then_span,
-                    Some(else_id),
-                    else_ty,
-                    else_span,
-                );
-                if let Some(ret_sp) = opt_suggest_box_span {
-                    self.suggest_boxing_for_return_impl_trait(
-                        err,
-                        ret_sp,
-                        [then_span, else_span].into_iter(),
-                    );
-                }
-            }
-            ObligationCauseCode::LetElse => {
-                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
-                err.help("...or use `match` instead of `let...else`");
-            }
-            _ => {
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
-                = cause.code().peel_derives()
-                    && let TypeError::RegionsPlaceholderMismatch = terr
-                {
-                    err.span_note( * span,
-                    "the lifetime requirement is introduced here");
-                }
-            }
-        }
-    }
-}
-
-impl<'tcx> InferCtxt<'tcx> {
-    /// Given a [`hir::Block`], get the span of its last expression or
-    /// statement, peeling off any inner blocks.
-    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
-        let block = block.innermost_block();
-        if let Some(expr) = &block.expr {
-            expr.span
-        } else if let Some(stmt) = block.stmts.last() {
-            // possibly incorrect trailing `;` in the else arm
-            stmt.span
-        } else {
-            // empty block; point at its entirety
-            block.span
-        }
-    }
-
-    /// Given a [`hir::HirId`] for a block, get the span of its last expression
-    /// or statement, peeling off any inner blocks.
-    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
-        match self.tcx.hir().get(hir_id) {
-            hir::Node::Block(blk) => self.find_block_span(blk),
-            // The parser was in a weird state if either of these happen, but
-            // it's better not to panic.
-            hir::Node::Expr(e) => e.span,
-            _ => rustc_span::DUMMY_SP,
-        }
-    }
-}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 1275d6f223c..44ee4172675 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -61,6 +61,7 @@ mod late;
 mod let_underscore;
 mod levels;
 mod methods;
+mod multiple_supertrait_upcastable;
 mod non_ascii_idents;
 mod non_fmt_panic;
 mod nonstandard_style;
@@ -95,6 +96,7 @@ use hidden_unicode_codepoints::*;
 use internal::*;
 use let_underscore::*;
 use methods::*;
+use multiple_supertrait_upcastable::*;
 use non_ascii_idents::*;
 use non_fmt_panic::NonPanicFmt;
 use nonstandard_style::*;
@@ -229,6 +231,7 @@ late_lint_methods!(
             InvalidAtomicOrdering: InvalidAtomicOrdering,
             NamedAsmLabels: NamedAsmLabels,
             OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
+            MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..5861b826b1c
--- /dev/null
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -0,0 +1,63 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_errors::DelayDm;
+use rustc_hir as hir;
+use rustc_span::sym;
+
+declare_lint! {
+    /// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
+    /// supertraits.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// trait A {}
+    /// trait B {}
+    ///
+    /// #[warn(multiple_supertrait_upcastable)]
+    /// trait C: A + B {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// To support upcasting with multiple supertraits, we need to store multiple vtables and this
+    /// can result in extra space overhead, even if no code actually uses upcasting.
+    /// This lint allows users to identify when such scenarios occur and to decide whether the
+    /// additional overhead is justified.
+    pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
+    Allow,
+    "detect when an object-safe trait has multiple supertraits",
+    @feature_gate = sym::multiple_supertrait_upcastable;
+}
+
+declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
+
+impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+        let def_id = item.owner_id.to_def_id();
+        if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
+            && cx.tcx.is_object_safe(def_id)
+        {
+            let direct_super_traits_iter = cx.tcx
+                    .super_predicates_of(def_id)
+                    .predicates
+                    .into_iter()
+                    .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
+            if direct_super_traits_iter.count() > 1 {
+                cx.struct_span_lint(
+                    MULTIPLE_SUPERTRAIT_UPCASTABLE,
+                    cx.tcx.def_span(def_id),
+                    DelayDm(|| {
+                        format!(
+                            "`{}` is object-safe and has multiple supertraits",
+                            item.ident,
+                        )
+                    }),
+                    |diag| diag,
+                );
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 90f654c68ec..da37dab6a9c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -943,6 +943,7 @@ symbols! {
         mul,
         mul_assign,
         mul_with_overflow,
+        multiple_supertrait_upcastable,
         must_not_suspend,
         must_use,
         naked,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index b154688fb08..b5fe8d72f7d 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -954,7 +954,7 @@ impl<T: ?Sized> Box<T> {
     /// [`Layout`]: crate::Layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
-    #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"]
+    #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
         unsafe { Self::from_raw_in(raw, Global) }
     }
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index 5a05215aeed..fe08e0e10e8 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -1,8 +1,8 @@
 use super::*;
 use crate::boxed::Box;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
 use std::iter::TrustedLen;
 use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicU32, Ordering};
 
 #[test]
 fn test_iterator() {
@@ -291,33 +291,83 @@ fn test_drain_sorted() {
 
 #[test]
 fn test_drain_sorted_leak() {
-    static DROPS: AtomicU32 = AtomicU32::new(0);
-
-    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
-    struct D(u32, bool);
-
-    impl Drop for D {
-        fn drop(&mut self) {
-            DROPS.fetch_add(1, Ordering::SeqCst);
-
-            if self.1 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
+    let d0 = CrashTestDummy::new(0);
+    let d1 = CrashTestDummy::new(1);
+    let d2 = CrashTestDummy::new(2);
+    let d3 = CrashTestDummy::new(3);
+    let d4 = CrashTestDummy::new(4);
+    let d5 = CrashTestDummy::new(5);
     let mut q = BinaryHeap::from(vec![
-        D(0, false),
-        D(1, false),
-        D(2, false),
-        D(3, true),
-        D(4, false),
-        D(5, false),
+        d0.spawn(Panic::Never),
+        d1.spawn(Panic::Never),
+        d2.spawn(Panic::Never),
+        d3.spawn(Panic::InDrop),
+        d4.spawn(Panic::Never),
+        d5.spawn(Panic::Never),
     ]);
 
-    catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok();
+    catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err();
+
+    assert_eq!(d0.dropped(), 1);
+    assert_eq!(d1.dropped(), 1);
+    assert_eq!(d2.dropped(), 1);
+    assert_eq!(d3.dropped(), 1);
+    assert_eq!(d4.dropped(), 1);
+    assert_eq!(d5.dropped(), 1);
+    assert!(q.is_empty());
+}
 
-    assert_eq!(DROPS.load(Ordering::SeqCst), 6);
+#[test]
+fn test_drain_forget() {
+    let a = CrashTestDummy::new(0);
+    let b = CrashTestDummy::new(1);
+    let c = CrashTestDummy::new(2);
+    let mut q =
+        BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]);
+
+    catch_unwind(AssertUnwindSafe(|| {
+        let mut it = q.drain();
+        it.next();
+        mem::forget(it);
+    }))
+    .unwrap();
+    // Behaviour after leaking is explicitly unspecified and order is arbitrary,
+    // so it's fine if these start failing, but probably worth knowing.
+    assert!(q.is_empty());
+    assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+    drop(q);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+}
+
+#[test]
+fn test_drain_sorted_forget() {
+    let a = CrashTestDummy::new(0);
+    let b = CrashTestDummy::new(1);
+    let c = CrashTestDummy::new(2);
+    let mut q =
+        BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]);
+
+    catch_unwind(AssertUnwindSafe(|| {
+        let mut it = q.drain_sorted();
+        it.next();
+        mem::forget(it);
+    }))
+    .unwrap();
+    // Behaviour after leaking is explicitly unspecified,
+    // so it's fine if these start failing, but probably worth knowing.
+    assert_eq!(q.len(), 2);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+    drop(q);
+    assert_eq!(a.dropped(), 1);
+    assert_eq!(b.dropped(), 1);
+    assert_eq!(c.dropped(), 1);
 }
 
 #[test]
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 4c372b1d60a..700b1463bfd 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1,12 +1,12 @@
-use super::super::testing::crash_test::{CrashTestDummy, Panic};
-use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor};
-use super::super::testing::rng::DeterministicRng;
 use super::Entry::{Occupied, Vacant};
 use super::*;
 use crate::boxed::Box;
 use crate::fmt::Debug;
 use crate::rc::Rc;
 use crate::string::{String, ToString};
+use crate::testing::crash_test::{CrashTestDummy, Panic};
+use crate::testing::ord_chaos::{Cyclic3, Governed, Governor};
+use crate::testing::rng::DeterministicRng;
 use crate::vec::Vec;
 use std::cmp::Ordering;
 use std::convert::TryFrom;
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index 9d43ac5c5be..7552f2fc04c 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -21,6 +21,3 @@ trait Recover<Q: ?Sized> {
     fn take(&mut self, key: &Q) -> Option<Self::Key>;
     fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
 }
-
-#[cfg(test)]
-mod testing;
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 502d3e1d126..7b8d41a6031 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -1,6 +1,6 @@
-use super::super::testing::crash_test::{CrashTestDummy, Panic};
-use super::super::testing::rng::DeterministicRng;
 use super::*;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
+use crate::testing::rng::DeterministicRng;
 use crate::vec::Vec;
 use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index f8fbfa1bfbc..5d5af22bb29 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -1,4 +1,5 @@
 use super::*;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
 use crate::vec::Vec;
 
 use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -984,35 +985,34 @@ fn drain_filter_complex() {
 
 #[test]
 fn drain_filter_drop_panic_leak() {
-    static mut DROPS: i32 = 0;
-
-    struct D(bool);
-
-    impl Drop for D {
-        fn drop(&mut self) {
-            unsafe {
-                DROPS += 1;
-            }
-
-            if self.0 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
+    let d0 = CrashTestDummy::new(0);
+    let d1 = CrashTestDummy::new(1);
+    let d2 = CrashTestDummy::new(2);
+    let d3 = CrashTestDummy::new(3);
+    let d4 = CrashTestDummy::new(4);
+    let d5 = CrashTestDummy::new(5);
+    let d6 = CrashTestDummy::new(6);
+    let d7 = CrashTestDummy::new(7);
     let mut q = LinkedList::new();
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_front(D(false));
-    q.push_front(D(true));
-    q.push_front(D(false));
-
-    catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok();
-
-    assert_eq!(unsafe { DROPS }, 8);
+    q.push_back(d3.spawn(Panic::Never));
+    q.push_back(d4.spawn(Panic::Never));
+    q.push_back(d5.spawn(Panic::Never));
+    q.push_back(d6.spawn(Panic::Never));
+    q.push_back(d7.spawn(Panic::Never));
+    q.push_front(d2.spawn(Panic::Never));
+    q.push_front(d1.spawn(Panic::InDrop));
+    q.push_front(d0.spawn(Panic::Never));
+
+    catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err();
+
+    assert_eq!(d0.dropped(), 1);
+    assert_eq!(d1.dropped(), 1);
+    assert_eq!(d2.dropped(), 1);
+    assert_eq!(d3.dropped(), 1);
+    assert_eq!(d4.dropped(), 1);
+    assert_eq!(d5.dropped(), 1);
+    assert_eq!(d6.dropped(), 1);
+    assert_eq!(d7.dropped(), 1);
     assert!(q.is_empty());
 }
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 96960d43f58..fb1664ba7a2 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -87,6 +87,7 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
 //
 // Library features:
 #![feature(alloc_layout_extra)]
@@ -190,6 +191,7 @@
 #![feature(unsized_fn_params)]
 #![feature(c_unwind)]
 #![feature(with_negative_coherence)]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
 //
 // Rustdoc features:
 #![feature(doc_cfg)]
@@ -206,6 +208,8 @@
 extern crate std;
 #[cfg(test)]
 extern crate test;
+#[cfg(test)]
+mod testing;
 
 // Module with internal macros used by other modules (needs to be included before other modules).
 #[macro_use]
diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs
index bcf5f5f7251..bcf5f5f7251 100644
--- a/library/alloc/src/collections/btree/testing/crash_test.rs
+++ b/library/alloc/src/testing/crash_test.rs
diff --git a/library/alloc/src/collections/btree/testing/mod.rs b/library/alloc/src/testing/mod.rs
index 7a094f8a595..7a094f8a595 100644
--- a/library/alloc/src/collections/btree/testing/mod.rs
+++ b/library/alloc/src/testing/mod.rs
diff --git a/library/alloc/src/collections/btree/testing/ord_chaos.rs b/library/alloc/src/testing/ord_chaos.rs
index 96ce7c15790..96ce7c15790 100644
--- a/library/alloc/src/collections/btree/testing/ord_chaos.rs
+++ b/library/alloc/src/testing/ord_chaos.rs
diff --git a/library/alloc/src/collections/btree/testing/rng.rs b/library/alloc/src/testing/rng.rs
index ecf543bee03..ecf543bee03 100644
--- a/library/alloc/src/collections/btree/testing/rng.rs
+++ b/library/alloc/src/testing/rng.rs
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 1a379ecc11c..9ca4947ed8f 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -148,7 +148,7 @@
 //! ```
 //!
 //! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then
-//! the `get_context_ref` call will return a reference to `obj.some_string` with type `&String`.
+//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 7152300abcb..d2fac23ff18 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -28,6 +28,7 @@ use crate::fmt::{Debug, Display};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
 #[rustc_has_incoherent_inherent_impls]
+#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
     ///
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 98734c527f2..617dfd12383 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -22,17 +22,12 @@ pub const fn empty<T>() -> Empty<T> {
     Empty(marker::PhantomData)
 }
 
-// Newtype for use in `PhantomData` to avoid
-// > error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`
-// in `const fn empty<T>()` above.
-struct FnReturning<T>(fn() -> T);
-
 /// An iterator that yields nothing.
 ///
 /// This `struct` is created by the [`empty()`] function. See its documentation for more.
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iter_empty", since = "1.2.0")]
-pub struct Empty<T>(marker::PhantomData<FnReturning<T>>);
+pub struct Empty<T>(marker::PhantomData<fn() -> T>);
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T> fmt::Debug for Empty<T> {
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 1823fd30062..825c8541f0d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -95,6 +95,7 @@
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
 //
 // Library features:
 #![feature(const_align_offset)]
@@ -231,6 +232,7 @@
 #![feature(unsized_fn_params)]
 #![feature(asm_const)]
 #![feature(const_transmute_copy)]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
 //
 // Target features:
 #![feature(arm_target_feature)]
diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs
index d0904b4b94c..e030c55ce8f 100644
--- a/library/std/src/sync/mpmc/utils.rs
+++ b/library/std/src/sync/mpmc/utils.rs
@@ -136,7 +136,7 @@ impl Backoff {
         }
     }
 
-    /// Returns `true` if exponential backoff has completed and blocking the thread is advised.
+    /// Returns `true` if quadratic backoff has completed and blocking the thread is advised.
     #[inline]
     pub fn is_completed(&self) -> bool {
         self.step.get() > YIELD_LIMIT
diff --git a/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..0467dea621b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+#![warn(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
new file mode 100644
index 00000000000..1f725f35417
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
@@ -0,0 +1,57 @@
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: `#[warn(unknown_lints)]` on by default
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: 6 warnings emitted
+
diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
index 72118275774..47ab613bec2 100644
--- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr
+++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
@@ -4,7 +4,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used
 LL |     Box::from_raw(ptr);
    |     ^^^^^^^^^^^^^^^^^^
    |
-   = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
+   = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`
 note: the lint level is defined here
   --> $DIR/must-use-box-from-raw.rs:5:9
    |
diff --git a/src/test/ui/match/single-line.rs b/src/test/ui/match/single-line.rs
new file mode 100644
index 00000000000..0f69d089f9a
--- /dev/null
+++ b/src/test/ui/match/single-line.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _ = match Some(42) { Some(x) => x, None => "" }; //~ ERROR E0308
+}
diff --git a/src/test/ui/match/single-line.stderr b/src/test/ui/match/single-line.stderr
new file mode 100644
index 00000000000..ec3b76e3f4d
--- /dev/null
+++ b/src/test/ui/match/single-line.stderr
@@ -0,0 +1,12 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/single-line.rs:2:52
+   |
+LL |     let _ = match Some(42) { Some(x) => x, None => "" };
+   |             --------------              -          ^^ expected integer, found `&str`
+   |             |                           |
+   |             |                           this is found to be of type `{integer}`
+   |             `match` arms have incompatible types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.rs b/src/test/ui/repr/transparent-enum-too-many-variants.rs
new file mode 100644
index 00000000000..0dd4b4e6846
--- /dev/null
+++ b/src/test/ui/repr/transparent-enum-too-many-variants.rs
@@ -0,0 +1,10 @@
+use std::mem::size_of;
+
+#[repr(transparent)]
+enum Foo { //~ ERROR E0731
+    A(u8), B(u8),
+}
+
+fn main() {
+    println!("Foo: {}", size_of::<Foo>());
+}
diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.stderr b/src/test/ui/repr/transparent-enum-too-many-variants.stderr
new file mode 100644
index 00000000000..fb44757efaf
--- /dev/null
+++ b/src/test/ui/repr/transparent-enum-too-many-variants.stderr
@@ -0,0 +1,11 @@
+error[E0731]: transparent enum needs exactly one variant, but has 2
+  --> $DIR/transparent-enum-too-many-variants.rs:4:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^ needs exactly one variant, but has 2
+LL |     A(u8), B(u8),
+   |     -      - too many variants in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0731`.
diff --git a/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..3c6ab86e4c6
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
@@ -0,0 +1,10 @@
+#![feature(multiple_supertrait_upcastable)]
+#![deny(multiple_supertrait_upcastable)]
+
+trait A {}
+trait B {}
+
+trait C: A + B {}
+//~^ ERROR `C` is object-safe and has multiple supertraits
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
new file mode 100644
index 00000000000..ad80a009ece
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
@@ -0,0 +1,14 @@
+error: `C` is object-safe and has multiple supertraits
+  --> $DIR/multiple_supertrait_upcastable.rs:7:1
+   |
+LL | trait C: A + B {}
+   | ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/multiple_supertrait_upcastable.rs:2:9
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+