about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-23 16:04:48 +0000
committerbors <bors@rust-lang.org>2023-10-23 16:04:48 +0000
commite2068cdb0964ccbae614ab60cddeed7b24473cdd (patch)
treea4cd4870acbbe4ecfe85061c8384359e33678b0b
parent858a42bf46a49bc64228d69b757294fe7a9bba6c (diff)
parentf4dfd8d497c1d9f9cc692e2d744220c578fa1c74 (diff)
downloadrust-e2068cdb0964ccbae614ab60cddeed7b24473cdd.tar.gz
rust-e2068cdb0964ccbae614ab60cddeed7b24473cdd.zip
Auto merge of #117087 - matthiaskrgr:rollup-08kkjkz, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - #116960 (Location-insensitive polonius: consider a loan escaping if an SCC has member constraints applied only)
 - #116978 (Rewrite gdb pretty-printer registration)
 - #117040 (coverage: Add UI tests for values accepted by `-Cinstrument-coverage`)
 - #117064 (Eliminate rustc_attrs::builtin::handle_errors in favor of emitting errors directly)
 - #117073 (Fix suggestion for renamed coroutines feature)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_attr/src/builtin.rs201
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs21
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs18
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_session/src/config.rs9
-rw-r--r--src/etc/gdb_lookup.py133
-rw-r--r--src/tools/compiletest/src/runtest.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/codegen/instrument-coverage-off.rs23
-rw-r--r--tests/codegen/instrument-coverage.rs9
-rw-r--r--tests/ui/instrument-coverage/bad-value.bad.stderr2
-rw-r--r--tests/ui/instrument-coverage/bad-value.blank.stderr2
-rw-r--r--tests/ui/instrument-coverage/bad-value.rs5
-rw-r--r--tests/ui/instrument-coverage/except-unused-functions.rs3
-rw-r--r--tests/ui/instrument-coverage/except-unused-functions.stderr2
-rw-r--r--tests/ui/instrument-coverage/except-unused-generics.rs3
-rw-r--r--tests/ui/instrument-coverage/except-unused-generics.stderr2
-rw-r--r--tests/ui/instrument-coverage/off-values.rs9
-rw-r--r--tests/ui/instrument-coverage/on-values.rs11
-rw-r--r--tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr36
-rw-r--r--tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr36
-rw-r--r--tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.rs33
22 files changed, 352 insertions, 212 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 46683d2d258..60eacde1c72 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -31,16 +31,6 @@ pub fn is_builtin_attr(attr: &Attribute) -> bool {
     attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
 }
 
-enum AttrError {
-    MultipleItem(String),
-    UnknownMetaItem(String, &'static [&'static str]),
-    MissingSince,
-    NonIdentFeature,
-    MissingFeature,
-    MultipleStabilityLevels,
-    UnsupportedLiteral(UnsupportedLiteralReason, /* is_bytestr */ bool),
-}
-
 pub(crate) enum UnsupportedLiteralReason {
     Generic,
     CfgString,
@@ -48,37 +38,6 @@ pub(crate) enum UnsupportedLiteralReason {
     DeprecatedKvPair,
 }
 
-fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
-    match error {
-        AttrError::MultipleItem(item) => {
-            sess.emit_err(session_diagnostics::MultipleItem { span, item });
-        }
-        AttrError::UnknownMetaItem(item, expected) => {
-            sess.emit_err(session_diagnostics::UnknownMetaItem { span, item, expected });
-        }
-        AttrError::MissingSince => {
-            sess.emit_err(session_diagnostics::MissingSince { span });
-        }
-        AttrError::NonIdentFeature => {
-            sess.emit_err(session_diagnostics::NonIdentFeature { span });
-        }
-        AttrError::MissingFeature => {
-            sess.emit_err(session_diagnostics::MissingFeature { span });
-        }
-        AttrError::MultipleStabilityLevels => {
-            sess.emit_err(session_diagnostics::MultipleStabilityLevels { span });
-        }
-        AttrError::UnsupportedLiteral(reason, is_bytestr) => {
-            sess.emit_err(session_diagnostics::UnsupportedLiteral {
-                span,
-                reason,
-                is_bytestr,
-                start_point_span: sess.source_map().start_point(span),
-            });
-        }
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum InlineAttr {
     None,
@@ -241,7 +200,7 @@ pub fn find_stability(
             sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
             sym::unstable => {
                 if stab.is_some() {
-                    handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
+                    sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
                     break;
                 }
 
@@ -251,7 +210,7 @@ pub fn find_stability(
             }
             sym::stable => {
                 if stab.is_some() {
-                    handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
+                    sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
                     break;
                 }
                 if let Some((feature, level)) = parse_stability(sess, attr) {
@@ -295,7 +254,7 @@ pub fn find_const_stability(
             sym::rustc_promotable => promotable = true,
             sym::rustc_const_unstable => {
                 if const_stab.is_some() {
-                    handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
+                    sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
                     break;
                 }
 
@@ -306,7 +265,7 @@ pub fn find_const_stability(
             }
             sym::rustc_const_stable => {
                 if const_stab.is_some() {
-                    handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
+                    sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
                     break;
                 }
                 if let Some((feature, level)) = parse_stability(sess, attr) {
@@ -340,7 +299,7 @@ pub fn find_body_stability(
     for attr in attrs {
         if attr.has_name(sym::rustc_default_body_unstable) {
             if body_stab.is_some() {
-                handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
+                sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
                 break;
             }
 
@@ -355,11 +314,10 @@ pub fn find_body_stability(
 
 fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {
     if item.is_some() {
-        handle_errors(
-            &sess.parse_sess,
-            meta.span,
-            AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-        );
+        sess.emit_err(session_diagnostics::MultipleItem {
+            span: meta.span,
+            item: pprust::path_to_string(&meta.path),
+        });
         None
     } else if let Some(v) = meta.value_str() {
         *item = Some(v);
@@ -380,11 +338,12 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
     let mut since = None;
     for meta in metas {
         let Some(mi) = meta.meta_item() else {
-            handle_errors(
-                &sess.parse_sess,
-                meta.span(),
-                AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
-            );
+            sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                span: meta.span(),
+                reason: UnsupportedLiteralReason::Generic,
+                is_bytestr: false,
+                start_point_span: sess.source_map().start_point(meta.span()),
+            });
             return None;
         };
 
@@ -392,14 +351,11 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
             sym::feature => insert_or_error(sess, mi, &mut feature)?,
             sym::since => insert_or_error(sess, mi, &mut since)?,
             _ => {
-                handle_errors(
-                    &sess.parse_sess,
-                    meta.span(),
-                    AttrError::UnknownMetaItem(
-                        pprust::path_to_string(&mi.path),
-                        &["feature", "since"],
-                    ),
-                );
+                sess.emit_err(session_diagnostics::UnknownMetaItem {
+                    span: meta.span(),
+                    item: pprust::path_to_string(&mi.path),
+                    expected: &["feature", "since"],
+                });
                 return None;
             }
         }
@@ -417,11 +373,11 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
             Some((feature, level))
         }
         (None, _) => {
-            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
+            sess.emit_err(session_diagnostics::MissingFeature { span: attr.span });
             None
         }
         _ => {
-            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
+            sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
             None
         }
     }
@@ -441,11 +397,12 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
     let mut implied_by = None;
     for meta in metas {
         let Some(mi) = meta.meta_item() else {
-            handle_errors(
-                &sess.parse_sess,
-                meta.span(),
-                AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
-            );
+            sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                span: meta.span(),
+                reason: UnsupportedLiteralReason::Generic,
+                is_bytestr: false,
+                start_point_span: sess.source_map().start_point(meta.span()),
+            });
             return None;
         };
 
@@ -484,14 +441,11 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
             }
             sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?,
             _ => {
-                handle_errors(
-                    &sess.parse_sess,
-                    meta.span(),
-                    AttrError::UnknownMetaItem(
-                        pprust::path_to_string(&mi.path),
-                        &["feature", "reason", "issue", "soft", "implied_by"],
-                    ),
-                );
+                sess.emit_err(session_diagnostics::UnknownMetaItem {
+                    span: meta.span(),
+                    item: pprust::path_to_string(&mi.path),
+                    expected: &["feature", "reason", "issue", "soft", "implied_by"],
+                });
                 return None;
             }
         }
@@ -500,7 +454,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
     match (feature, reason, issue) {
         (Some(feature), reason, Some(_)) => {
             if !rustc_lexer::is_ident(feature.as_str()) {
-                handle_errors(&sess.parse_sess, attr.span, AttrError::NonIdentFeature);
+                sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span });
                 return None;
             }
             let level = StabilityLevel::Unstable {
@@ -512,7 +466,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
             Some((feature, level))
         }
         (None, _, _) => {
-            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
+            sess.emit_err(session_diagnostics::MissingFeature { span: attr.span });
             return None;
         }
         _ => {
@@ -659,11 +613,12 @@ pub fn eval_condition(
         ast::MetaItemKind::List(mis) => {
             for mi in mis.iter() {
                 if !mi.is_meta_item() {
-                    handle_errors(
-                        sess,
-                        mi.span(),
-                        AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
-                    );
+                    sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                        span: mi.span(),
+                        reason: UnsupportedLiteralReason::Generic,
+                        is_bytestr: false,
+                        start_point_span: sess.source_map().start_point(mi.span()),
+                    });
                     return false;
                 }
             }
@@ -731,14 +686,12 @@ pub fn eval_condition(
             true
         }
         MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-            handle_errors(
-                sess,
-                lit.span,
-                AttrError::UnsupportedLiteral(
-                    UnsupportedLiteralReason::CfgString,
-                    lit.kind.is_bytestr(),
-                ),
-            );
+            sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                span: lit.span,
+                reason: UnsupportedLiteralReason::CfgString,
+                is_bytestr: lit.kind.is_bytestr(),
+                start_point_span: sess.source_map().start_point(lit.span),
+            });
             true
         }
         ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
@@ -795,11 +748,10 @@ pub fn find_deprecation(
             MetaItemKind::List(list) => {
                 let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                     if item.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            meta.span,
-                            AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-                        );
+                        sess.emit_err(session_diagnostics::MultipleItem {
+                            span: meta.span,
+                            item: pprust::path_to_string(&meta.path),
+                        });
                         return false;
                     }
                     if let Some(v) = meta.value_str() {
@@ -807,14 +759,12 @@ pub fn find_deprecation(
                         true
                     } else {
                         if let Some(lit) = meta.name_value_literal() {
-                            handle_errors(
-                                &sess.parse_sess,
-                                lit.span,
-                                AttrError::UnsupportedLiteral(
-                                    UnsupportedLiteralReason::DeprecatedString,
-                                    lit.kind.is_bytestr(),
-                                ),
-                            );
+                            sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                                span: lit.span,
+                                reason: UnsupportedLiteralReason::DeprecatedString,
+                                is_bytestr: lit.kind.is_bytestr(),
+                                start_point_span: sess.source_map().start_point(lit.span),
+                            });
                         } else {
                             sess.emit_err(session_diagnostics::IncorrectMetaItem {
                                 span: meta.span,
@@ -852,30 +802,25 @@ pub fn find_deprecation(
                                 }
                             }
                             _ => {
-                                handle_errors(
-                                    &sess.parse_sess,
-                                    meta.span(),
-                                    AttrError::UnknownMetaItem(
-                                        pprust::path_to_string(&mi.path),
-                                        if features.deprecated_suggestion {
-                                            &["since", "note", "suggestion"]
-                                        } else {
-                                            &["since", "note"]
-                                        },
-                                    ),
-                                );
+                                sess.emit_err(session_diagnostics::UnknownMetaItem {
+                                    span: meta.span(),
+                                    item: pprust::path_to_string(&mi.path),
+                                    expected: if features.deprecated_suggestion {
+                                        &["since", "note", "suggestion"]
+                                    } else {
+                                        &["since", "note"]
+                                    },
+                                });
                                 continue 'outer;
                             }
                         },
                         NestedMetaItem::Lit(lit) => {
-                            handle_errors(
-                                &sess.parse_sess,
-                                lit.span,
-                                AttrError::UnsupportedLiteral(
-                                    UnsupportedLiteralReason::DeprecatedKvPair,
-                                    false,
-                                ),
-                            );
+                            sess.emit_err(session_diagnostics::UnsupportedLiteral {
+                                span: lit.span,
+                                reason: UnsupportedLiteralReason::DeprecatedKvPair,
+                                is_bytestr: false,
+                                start_point_span: sess.source_map().start_point(lit.span),
+                            });
                             continue 'outer;
                         }
                     }
@@ -885,7 +830,7 @@ pub fn find_deprecation(
 
         if is_rustc {
             if since.is_none() {
-                handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
+                sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
                 continue;
             }
 
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 6ea84620bbe..16814950b0d 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -272,21 +272,28 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
         loan_issued_at: Location,
     ) {
         let sccs = self.regioncx.constraint_sccs();
+        let universal_regions = self.regioncx.universal_regions();
         let issuing_region_scc = sccs.scc(issuing_region);
 
         // We first handle the cases where the loan doesn't go out of scope, depending on the issuing
         // region's successors.
         for scc in sccs.depth_first_search(issuing_region_scc) {
-            // 1. Via member constraints
+            // 1. Via applied member constraints
             //
             // The issuing region can flow into the choice regions, and they are either:
             // - placeholders or free regions themselves,
             // - or also transitively outlive a free region.
             //
-            // That is to say, if there are member constraints here, the loan escapes the function
-            // and cannot go out of scope. We can early return.
-            if self.regioncx.scc_has_member_constraints(scc) {
-                return;
+            // That is to say, if there are applied member constraints here, the loan escapes the
+            // function and cannot go out of scope. We could early return here.
+            //
+            // For additional insurance via fuzzing and crater, we verify that the constraint's min
+            // choice indeed escapes the function. In the future, we could e.g. turn this check into
+            // a debug assert and early return as an optimization.
+            for constraint in self.regioncx.applied_member_constraints(scc) {
+                if universal_regions.is_universal_region(constraint.min_choice) {
+                    return;
+                }
             }
 
             // 2. Via regions that are live at all points: placeholders and free regions.
@@ -413,12 +420,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
             let mut polonius_prec = PoloniusOutOfScopePrecomputer::new(body, regioncx);
             for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
                 let issuing_region = loan_data.region;
-                let issued_location = loan_data.reserve_location;
+                let loan_issued_at = loan_data.reserve_location;
 
                 polonius_prec.precompute_loans_out_of_scope(
                     loan_idx,
                     issuing_region,
-                    issued_location,
+                    loan_issued_at,
                 );
             }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 96cbe98c216..05c2cbd4969 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -644,11 +644,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.scc_universes[scc]
     }
 
-    /// Once region solving has completed, this function will return
-    /// the member constraints that were applied to the value of a given
-    /// region `r`. See `AppliedMemberConstraint`.
-    pub(crate) fn applied_member_constraints(&self, r: RegionVid) -> &[AppliedMemberConstraint] {
-        let scc = self.constraint_sccs.scc(r);
+    /// Once region solving has completed, this function will return the member constraints that
+    /// were applied to the value of a given SCC `scc`. See `AppliedMemberConstraint`.
+    pub(crate) fn applied_member_constraints(
+        &self,
+        scc: ConstraintSccIndex,
+    ) -> &[AppliedMemberConstraint] {
         binary_search_util::binary_search_slice(
             &self.member_constraints_applied,
             |applied| applied.member_region_scc,
@@ -1945,7 +1946,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // Member constraints can also give rise to `'r: 'x` edges that
             // were not part of the graph initially, so watch out for those.
             // (But they are extremely rare; this loop is very cold.)
-            for constraint in self.applied_member_constraints(r) {
+            for constraint in self.applied_member_constraints(self.constraint_sccs.scc(r)) {
                 let p_c = &self.member_constraints[constraint.member_constraint_index];
                 let constraint = OutlivesConstraint {
                     sup: r,
@@ -2292,11 +2293,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.constraint_sccs.as_ref()
     }
 
-    /// Returns whether the given SCC has any member constraints.
-    pub(crate) fn scc_has_member_constraints(&self, scc: ConstraintSccIndex) -> bool {
-        self.member_constraints.indices(scc).next().is_some()
-    }
-
     /// Returns whether the given SCC is live at all points: whether the representative is a
     /// placeholder or a free region.
     pub(crate) fn scc_is_live_at_all_points(&self, scc: ConstraintSccIndex) -> bool {
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index ac133f8b039..ed19274a7cc 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -99,7 +99,7 @@ declare_features! (
     /// Allows generators to be cloned.
     (removed, generator_clone, "1.65.0", Some(95360), None, Some("renamed to `coroutine_clone`")),
     /// Allows defining generators.
-    (removed, generators, "1.21.0", Some(43122), None, Some("renamed to `coroutine`")),
+    (removed, generators, "1.21.0", Some(43122), None, Some("renamed to `coroutines`")),
     /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
     (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
      Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 2e991b4c0ad..462e7e85c65 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -3463,9 +3463,10 @@ impl DumpMonoStatsFormat {
 
 /// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
 /// or future prototype.
-#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
 pub enum Polonius {
     /// The default value: disabled.
+    #[default]
     Off,
 
     /// Legacy version, using datalog and the `polonius-engine` crate. Historical value for `-Zpolonius`.
@@ -3475,12 +3476,6 @@ pub enum Polonius {
     Next,
 }
 
-impl Default for Polonius {
-    fn default() -> Self {
-        Polonius::Off
-    }
-}
-
 impl Polonius {
     /// Returns whether the legacy version of polonius is enabled
     pub fn is_legacy_enabled(&self) -> bool {
diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py
index 8171cb4e9a6..f3ac9c10978 100644
--- a/src/etc/gdb_lookup.py
+++ b/src/etc/gdb_lookup.py
@@ -1,4 +1,5 @@
 import gdb
+import gdb.printing
 import re
 
 from gdb_providers import *
@@ -9,7 +10,7 @@ _gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
 gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
 
 def register_printers(objfile):
-    objfile.pretty_printers.append(lookup)
+    objfile.pretty_printers.append(printer)
 
 
 # BACKCOMPAT: rust 1.35
@@ -38,58 +39,80 @@ def check_enum_discriminant(valobj):
     return True
 
 
-def lookup(valobj):
-    rust_type = classify_rust_type(valobj.type)
-
-    if rust_type == RustType.ENUM:
-        # use enum provider only for GDB <7.12
-        if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12):
-            if check_enum_discriminant(valobj):
-                return EnumProvider(valobj)
-
-    if rust_type == RustType.STD_STRING:
-        return StdStringProvider(valobj)
-    if rust_type == RustType.STD_OS_STRING:
-        return StdOsStringProvider(valobj)
-    if rust_type == RustType.STD_STR:
-        return StdStrProvider(valobj)
-    if rust_type == RustType.STD_SLICE:
-        return StdSliceProvider(valobj)
-    if rust_type == RustType.STD_VEC:
-        return StdVecProvider(valobj)
-    if rust_type == RustType.STD_VEC_DEQUE:
-        return StdVecDequeProvider(valobj)
-    if rust_type == RustType.STD_BTREE_SET:
-        return StdBTreeSetProvider(valobj)
-    if rust_type == RustType.STD_BTREE_MAP:
-        return StdBTreeMapProvider(valobj)
-    if rust_type == RustType.STD_HASH_MAP:
-        if is_hashbrown_hashmap(valobj):
-            return StdHashMapProvider(valobj)
-        else:
-            return StdOldHashMapProvider(valobj)
-    if rust_type == RustType.STD_HASH_SET:
-        hash_map = valobj[valobj.type.fields()[0]]
-        if is_hashbrown_hashmap(hash_map):
-            return StdHashMapProvider(valobj, show_values=False)
-        else:
-            return StdOldHashMapProvider(hash_map, show_values=False)
-
-    if rust_type == RustType.STD_RC:
-        return StdRcProvider(valobj)
-    if rust_type == RustType.STD_ARC:
-        return StdRcProvider(valobj, is_atomic=True)
-
-    if rust_type == RustType.STD_CELL:
-        return StdCellProvider(valobj)
-    if rust_type == RustType.STD_REF:
-        return StdRefProvider(valobj)
-    if rust_type == RustType.STD_REF_MUT:
-        return StdRefProvider(valobj)
-    if rust_type == RustType.STD_REF_CELL:
-        return StdRefCellProvider(valobj)
-
-    if rust_type == RustType.STD_NONZERO_NUMBER:
-        return StdNonZeroNumberProvider(valobj)
-
+# Helper for enum printing that checks the discriminant.  Only used in
+# older gdb.
+def enum_provider(valobj):
+    if check_enum_discriminant(valobj):
+        return EnumProvider(valobj)
     return None
+
+
+# Helper to handle both old and new hash maps.
+def hashmap_provider(valobj):
+    if is_hashbrown_hashmap(valobj):
+        return StdHashMapProvider(valobj)
+    else:
+        return StdOldHashMapProvider(valobj)
+
+
+# Helper to handle both old and new hash sets.
+def hashset_provider(valobj):
+    hash_map = valobj[valobj.type.fields()[0]]
+    if is_hashbrown_hashmap(hash_map):
+        return StdHashMapProvider(valobj, show_values=False)
+    else:
+        return StdOldHashMapProvider(hash_map, show_values=False)
+
+
+class PrintByRustType(gdb.printing.SubPrettyPrinter):
+    def __init__(self, name, provider):
+        super(PrintByRustType, self).__init__(name)
+        self.provider = provider
+
+    def __call__(self, val):
+        if self.enabled:
+            return self.provider(val)
+        return None
+
+
+class RustPrettyPrinter(gdb.printing.PrettyPrinter):
+    def __init__(self, name):
+        super(RustPrettyPrinter, self).__init__(name, [])
+        self.type_map = {}
+
+    def add(self, rust_type, provider):
+        # Just use the rust_type as the name.
+        printer = PrintByRustType(rust_type, provider)
+        self.type_map[rust_type] = printer
+        self.subprinters.append(printer)
+
+    def __call__(self, valobj):
+        rust_type = classify_rust_type(valobj.type)
+        if rust_type in self.type_map:
+            return self.type_map[rust_type](valobj)
+        return None
+
+
+printer = RustPrettyPrinter("rust")
+# use enum provider only for GDB <7.12
+if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12):
+    printer.add(RustType.ENUM, enum_provider)
+printer.add(RustType.STD_STRING, StdStringProvider)
+printer.add(RustType.STD_OS_STRING, StdOsStringProvider)
+printer.add(RustType.STD_STR, StdStrProvider)
+printer.add(RustType.STD_SLICE, StdSliceProvider)
+printer.add(RustType.STD_VEC, StdVecProvider)
+printer.add(RustType.STD_VEC_DEQUE, StdVecDequeProvider)
+printer.add(RustType.STD_BTREE_SET, StdBTreeSetProvider)
+printer.add(RustType.STD_BTREE_MAP, StdBTreeMapProvider)
+printer.add(RustType.STD_HASH_MAP, hashmap_provider)
+printer.add(RustType.STD_HASH_SET, hashset_provider)
+printer.add(RustType.STD_RC, StdRcProvider)
+printer.add(RustType.STD_ARC, lambda valobj: StdRcProvider(valobj, is_atomic=True))
+
+printer.add(RustType.STD_CELL, StdCellProvider)
+printer.add(RustType.STD_REF, StdRefProvider)
+printer.add(RustType.STD_REF_MUT, StdRefProvider)
+printer.add(RustType.STD_REF_CELL, StdRefCellProvider)
+
+printer.add(RustType.STD_NONZERO_NUMBER, StdNonZeroNumberProvider)
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 8ce00e00b57..ac270a1f0ba 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2470,7 +2470,7 @@ impl<'test> TestCx<'test> {
             }
             CoverageMap => {
                 rustc.arg("-Cinstrument-coverage");
-                // These tests only compile to MIR, so they don't need the
+                // These tests only compile to LLVM IR, so they don't need the
                 // profiler runtime to be present.
                 rustc.arg("-Zno-profiler-runtime");
                 // Coverage mappings are sensitive to MIR optimizations, and
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 2b828e58d54..dcf218bc189 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1854;
-const ROOT_ENTRY_LIMIT: usize = 865;
+const ROOT_ENTRY_LIMIT: usize = 866;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/codegen/instrument-coverage-off.rs b/tests/codegen/instrument-coverage-off.rs
new file mode 100644
index 00000000000..ca803beec0b
--- /dev/null
+++ b/tests/codegen/instrument-coverage-off.rs
@@ -0,0 +1,23 @@
+// Test that `-Cinstrument-coverage=off` does not add coverage instrumentation to LLVM IR.
+
+// needs-profiler-support
+// revisions: n no off false zero
+// [n] compile-flags: -Cinstrument-coverage=n
+// [no] compile-flags: -Cinstrument-coverage=no
+// [off] compile-flags: -Cinstrument-coverage=off
+// [false] compile-flags: -Cinstrument-coverage=false
+// [zero] compile-flags: -Cinstrument-coverage=0
+
+// CHECK-NOT: __llvm_profile_filename
+// CHECK-NOT: __llvm_coverage_mapping
+
+#![crate_type="lib"]
+
+#[inline(never)]
+fn some_function() {
+
+}
+
+pub fn some_other_function() {
+    some_function();
+}
diff --git a/tests/codegen/instrument-coverage.rs b/tests/codegen/instrument-coverage.rs
index 78f8875a2d9..f8437dac463 100644
--- a/tests/codegen/instrument-coverage.rs
+++ b/tests/codegen/instrument-coverage.rs
@@ -1,9 +1,16 @@
 // Test that `-Cinstrument-coverage` creates expected __llvm_profile_filename symbol in LLVM IR.
 
 // needs-profiler-support
-// compile-flags: -Cinstrument-coverage
+// revisions: default y yes on true all
+// [default] compile-flags: -Cinstrument-coverage
+// [y] compile-flags: -Cinstrument-coverage=y
+// [yes] compile-flags: -Cinstrument-coverage=yes
+// [on] compile-flags: -Cinstrument-coverage=on
+// [true] compile-flags: -Cinstrument-coverage=true
+// [all] compile-flags: -Cinstrument-coverage=all
 
 // CHECK: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}}
+// CHECK: @__llvm_coverage_mapping
 
 #![crate_type="lib"]
 
diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr
new file mode 100644
index 00000000000..246c4f31a4b
--- /dev/null
+++ b/tests/ui/instrument-coverage/bad-value.bad.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
+
diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr
new file mode 100644
index 00000000000..b539c558d9b
--- /dev/null
+++ b/tests/ui/instrument-coverage/bad-value.blank.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
+
diff --git a/tests/ui/instrument-coverage/bad-value.rs b/tests/ui/instrument-coverage/bad-value.rs
new file mode 100644
index 00000000000..1925c36aa53
--- /dev/null
+++ b/tests/ui/instrument-coverage/bad-value.rs
@@ -0,0 +1,5 @@
+// revisions: blank bad
+// [blank] compile-flags: -Cinstrument-coverage=
+// [bad] compile-flags: -Cinstrument-coverage=bad-value
+
+fn main() {}
diff --git a/tests/ui/instrument-coverage/except-unused-functions.rs b/tests/ui/instrument-coverage/except-unused-functions.rs
new file mode 100644
index 00000000000..5a0b7d4fef9
--- /dev/null
+++ b/tests/ui/instrument-coverage/except-unused-functions.rs
@@ -0,0 +1,3 @@
+// compile-flags: -Cinstrument-coverage=except-unused-functions
+
+fn main() {}
diff --git a/tests/ui/instrument-coverage/except-unused-functions.stderr b/tests/ui/instrument-coverage/except-unused-functions.stderr
new file mode 100644
index 00000000000..82c1c630cbf
--- /dev/null
+++ b/tests/ui/instrument-coverage/except-unused-functions.stderr
@@ -0,0 +1,2 @@
+error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
+
diff --git a/tests/ui/instrument-coverage/except-unused-generics.rs b/tests/ui/instrument-coverage/except-unused-generics.rs
new file mode 100644
index 00000000000..4b1ddf29026
--- /dev/null
+++ b/tests/ui/instrument-coverage/except-unused-generics.rs
@@ -0,0 +1,3 @@
+// compile-flags: -Cinstrument-coverage=except-unused-generics
+
+fn main() {}
diff --git a/tests/ui/instrument-coverage/except-unused-generics.stderr b/tests/ui/instrument-coverage/except-unused-generics.stderr
new file mode 100644
index 00000000000..82c1c630cbf
--- /dev/null
+++ b/tests/ui/instrument-coverage/except-unused-generics.stderr
@@ -0,0 +1,2 @@
+error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
+
diff --git a/tests/ui/instrument-coverage/off-values.rs b/tests/ui/instrument-coverage/off-values.rs
new file mode 100644
index 00000000000..0f9a0c47425
--- /dev/null
+++ b/tests/ui/instrument-coverage/off-values.rs
@@ -0,0 +1,9 @@
+// check-pass
+// revisions: n no off false zero
+// [n] compile-flags: -Cinstrument-coverage=n
+// [no] compile-flags: -Cinstrument-coverage=no
+// [off] compile-flags: -Cinstrument-coverage=off
+// [false] compile-flags: -Cinstrument-coverage=false
+// [zero] compile-flags: -Cinstrument-coverage=0
+
+fn main() {}
diff --git a/tests/ui/instrument-coverage/on-values.rs b/tests/ui/instrument-coverage/on-values.rs
new file mode 100644
index 00000000000..cc54c71c656
--- /dev/null
+++ b/tests/ui/instrument-coverage/on-values.rs
@@ -0,0 +1,11 @@
+// check-pass
+// needs-profiler-support
+// revisions: default y yes on true all
+// [default] compile-flags: -Cinstrument-coverage
+// [y] compile-flags: -Cinstrument-coverage=y
+// [yes] compile-flags: -Cinstrument-coverage=yes
+// [on] compile-flags: -Cinstrument-coverage=on
+// [true] compile-flags: -Cinstrument-coverage=true
+// [all] compile-flags: -Cinstrument-coverage=all
+
+fn main() {}
diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr
new file mode 100644
index 00000000000..6f9b3303163
--- /dev/null
+++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.nll.stderr
@@ -0,0 +1,36 @@
+error[E0046]: not all trait items implemented, missing: `call`
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:18:1
+   |
+LL |     fn call(x: Self) -> Self::Output;
+   |     --------------------------------- `call` from trait
+...
+LL | impl<T: PlusOne> Callable for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
+
+error: unconstrained opaque type
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:22:19
+   |
+LL |     type Output = impl PlusOne;
+   |                   ^^^^^^^^^^^^
+   |
+   = note: `Output` must be used in combination with a concrete type within the same impl
+
+error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:28:5
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
+   |         --                     ------------ opaque type defined here
+   |         |
+   |         hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
+LL |     <&mut i32 as Callable>::call(y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a {
+   |                                             ++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0046, E0700.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr
new file mode 100644
index 00000000000..6f9b3303163
--- /dev/null
+++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.polonius.stderr
@@ -0,0 +1,36 @@
+error[E0046]: not all trait items implemented, missing: `call`
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:18:1
+   |
+LL |     fn call(x: Self) -> Self::Output;
+   |     --------------------------------- `call` from trait
+...
+LL | impl<T: PlusOne> Callable for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
+
+error: unconstrained opaque type
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:22:19
+   |
+LL |     type Output = impl PlusOne;
+   |                   ^^^^^^^^^^^^
+   |
+   = note: `Output` must be used in combination with a concrete type within the same impl
+
+error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
+  --> $DIR/location-insensitive-scopes-issue-116657.rs:28:5
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
+   |         --                     ------------ opaque type defined here
+   |         |
+   |         hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
+LL |     <&mut i32 as Callable>::call(y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a {
+   |                                             ++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0046, E0700.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.rs
new file mode 100644
index 00000000000..ec17e0b093b
--- /dev/null
+++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-116657.rs
@@ -0,0 +1,33 @@
+// This is a non-regression test for issue #116657, where NLL and `-Zpolonius=next` computed
+// different loan scopes when a member constraint was not ultimately applied.
+
+// revisions: nll polonius
+// [polonius] compile-flags: -Zpolonius=next
+
+#![feature(impl_trait_in_assoc_type)]
+
+trait Callable {
+    type Output;
+    fn call(x: Self) -> Self::Output;
+}
+
+trait PlusOne {}
+
+impl<'a> PlusOne for &'a mut i32 {}
+
+impl<T: PlusOne> Callable for T {
+    //[nll]~^ ERROR not all trait items implemented
+    //[polonius]~^^ ERROR not all trait items implemented
+
+    type Output = impl PlusOne;
+    //[nll]~^ ERROR unconstrained opaque type
+    //[polonius]~^^ ERROR unconstrained opaque type
+}
+
+fn test<'a>(y: &'a mut i32) -> impl PlusOne {
+    <&mut i32 as Callable>::call(y)
+    //[nll]~^ ERROR hidden type for `impl PlusOne` captures lifetime
+    //[polonius]~^^ ERROR hidden type for `impl PlusOne` captures lifetime
+}
+
+fn main() {}