about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-09 08:16:26 +0000
committerbors <bors@rust-lang.org>2023-05-09 08:16:26 +0000
commitecd3dbab4ed82abfa05e22069261e565239449cf (patch)
tree03ec27f0a1765fca86fd800b41e83c39c0bd529d /compiler/rustc_hir_analysis/src
parent7e7483d26e3cec7a44ef00cf7ae6c9c8c918bec6 (diff)
parent9d913eb9e4eb2a433e8755e1359c1cccb344ad3f (diff)
downloadrust-ecd3dbab4ed82abfa05e22069261e565239449cf.tar.gz
rust-ecd3dbab4ed82abfa05e22069261e565239449cf.zip
Auto merge of #111380 - Dylan-DPC:rollup-xiptbhn, r=Dylan-DPC
Rollup of 7 pull requests

Successful merges:

 - #110304 (Add GNU Property Note)
 - #110504 (Tweak borrow suggestion span)
 - #110583 (tweak "make mut" spans when assigning to locals)
 - #110694 (Implement builtin # syntax and use it for offset_of!(...))
 - #111120 (Suggest let for possible binding with ty)
 - #111252 (Min specialization improvements)
 - #111361 (Update books)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs34
2 files changed, 39 insertions, 4 deletions
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 379a88538a9..6e7eb4f6cdc 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -815,6 +815,15 @@ pub(crate) struct ClosureImplicitHrtb {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_empty_specialization)]
+pub(crate) struct EmptySpecialization {
+    #[primary_span]
+    pub span: Span,
+    #[note]
+    pub base_impl_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_const_specialize)]
 pub(crate) struct ConstSpecialize {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 5cca2dacb5c..e84da2519ae 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -80,7 +80,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
+use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
 
 pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
@@ -100,12 +100,19 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
         // Implementing a normal trait isn't a specialization.
         return None;
     }
+    if trait_def.is_marker {
+        // Overlapping marker implementations are not really specializations.
+        return None;
+    }
     Some(impl2_node)
 }
 
 /// Check that `impl1` is a sound specialization
 #[instrument(level = "debug", skip(tcx))]
 fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+    let span = tcx.def_span(impl1_def_id);
+    check_has_items(tcx, impl1_def_id, impl2_node, span);
+
     if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
         let impl2_def_id = impl2_node.def_id();
         debug!(?impl2_def_id, ?impl2_substs);
@@ -116,7 +123,6 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
             unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
         };
 
-        let span = tcx.def_span(impl1_def_id);
         check_constness(tcx, impl1_def_id, impl2_node, span);
         check_static_lifetimes(tcx, &parent_substs, span);
         check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
@@ -124,6 +130,13 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
     }
 }
 
+fn check_has_items(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
+    if let Node::Impl(impl2_id) = impl2_node && tcx.associated_item_def_ids(impl1_def_id).is_empty() {
+        let base_impl_span = tcx.def_span(impl2_id);
+        tcx.sess.emit_err(errors::EmptySpecialization { span, base_impl_span });
+    }
+}
+
 /// Check that the specializing impl `impl1` is at least as const as the base
 /// impl `impl2`
 fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
@@ -167,8 +180,21 @@ fn get_impl_substs(
         ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
 
     let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
-    let impl2_substs =
-        translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+    let impl1_span = tcx.def_span(impl1_def_id);
+    let impl2_substs = translate_substs_with_cause(
+        infcx,
+        param_env,
+        impl1_def_id.to_def_id(),
+        impl1_substs,
+        impl2_node,
+        |_, span| {
+            traits::ObligationCause::new(
+                impl1_span,
+                impl1_def_id,
+                traits::ObligationCauseCode::BindingObligation(impl2_node.def_id(), span),
+            )
+        },
+    );
 
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {