about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTaylor Yu <tlyu@mit.edu>2021-06-18 14:13:12 -0500
committerTaylor Yu <tlyu@mit.edu>2021-11-15 22:31:55 -0600
commitc9fcbda389adfffd72405905de67be1aa444820f (patch)
treeb3967d4f2483fac5be51a5ca302e9ebeee2a2c9b
parentb0535508474fb4353a3b83ef79df87817f028a71 (diff)
downloadrust-c9fcbda389adfffd72405905de67be1aa444820f.tar.gz
rust-c9fcbda389adfffd72405905de67be1aa444820f.zip
check where clause before suggesting unsized
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs19
-rw-r--r--src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs8
-rw-r--r--src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr18
3 files changed, 45 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 79194718d1e..305af6db298 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -14,6 +14,7 @@ use crate::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::GenericParam;
@@ -2009,6 +2010,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             Some(param) => param,
             _ => return,
         };
+        let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id();
+        let preds = generics.where_clause.predicates.iter();
+        let explicitly_sized = preds
+            .filter_map(|pred| match pred {
+                hir::WherePredicate::BoundPredicate(bp) => Some(bp),
+                _ => None,
+            })
+            .flat_map(|bp| match bp.bounded_ty.kind {
+                hir::TyKind::Path(hir::QPath::Resolved(
+                    None,
+                    &hir::Path { res: Res::Def(DefKind::TyParam, def_id), .. },
+                )) if def_id == param_def_id => bp.bounds,
+                _ => &[][..],
+            })
+            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
+        if explicitly_sized {
+            return;
+        }
         debug!("maybe_suggest_unsized_generics: param={:?}", param);
         match node {
             hir::Node::Item(
diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
new file mode 100644
index 00000000000..5cfaf4be96a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
@@ -0,0 +1,8 @@
+// Regression test for #85945: Don't suggest `?Sized` bound if an explicit
+// `Sized` bound is already in a `where` clause.
+fn foo<T>(_: &T) where T: Sized {}
+fn bar() { foo(""); }
+//~^ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
new file mode 100644
index 00000000000..92be9f764cc
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16
+   |
+LL | fn bar() { foo(""); }
+   |            --- ^^ doesn't have a size known at compile-time
+   |            |
+   |            required by a bound introduced by this call
+   |
+   = help: the trait `Sized` is not implemented for `str`
+note: required by a bound in `foo`
+  --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8
+   |
+LL | fn foo<T>(_: &T) where T: Sized {}
+   |        ^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.