]> git.lizzy.rs Git - rust.git/commitdiff
Point at `Sized` requirements
authorEsteban Küber <esteban@kuber.com.ar>
Fri, 31 Jan 2020 04:12:46 +0000 (20:12 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Sun, 2 Feb 2020 19:53:10 +0000 (11:53 -0800)
Make #47990 easier to understand

src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/suggest.rs
src/test/ui/issues/issue-35976.stderr
src/test/ui/suggestions/imm-ref-trait-object.stderr
src/test/ui/unsized-locals/by-value-trait-object-safety.stderr

index 832aa9f62ff4dc097ce8860a001d63db584e7992..eee9dc99d35b473cbbb65a35ca227d7f0b97f32d 100644 (file)
@@ -32,7 +32,7 @@ fn deref(&self) -> &Self::Target {
 
 pub struct ConfirmResult<'tcx> {
     pub callee: MethodCallee<'tcx>,
-    pub illegal_sized_bound: bool,
+    pub illegal_sized_bound: Option<Span>,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -112,7 +112,7 @@ fn confirm(
         // Add any trait/regions obligations specified on the method's type parameters.
         // We won't add these if we encountered an illegal sized bound, so that we can use
         // a custom error in that case.
-        if !illegal_sized_bound {
+        if illegal_sized_bound.is_none() {
             let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
             self.add_obligations(method_ty, all_substs, &method_predicates);
         }
@@ -561,23 +561,31 @@ fn convert_place_op_to_mutable(
     fn predicates_require_illegal_sized_bound(
         &self,
         predicates: &ty::InstantiatedPredicates<'tcx>,
-    ) -> bool {
+    ) -> Option<Span> {
         let sized_def_id = match self.tcx.lang_items().sized_trait() {
             Some(def_id) => def_id,
-            None => return false,
+            None => return None,
         };
 
         traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
             .filter_map(|predicate| match predicate {
                 ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
-                    Some(trait_pred)
+                    let span = predicates
+                        .predicates
+                        .iter()
+                        .zip(predicates.spans.iter())
+                        .filter_map(|(p, span)| if *p == predicate { Some(*span) } else { None })
+                        .next()
+                        .unwrap_or(rustc_span::DUMMY_SP);
+                    Some((trait_pred, span))
                 }
                 _ => None,
             })
-            .any(|trait_pred| match trait_pred.skip_binder().self_ty().kind {
-                ty::Dynamic(..) => true,
-                _ => false,
+            .filter_map(|(trait_pred, span)| match trait_pred.skip_binder().self_ty().kind {
+                ty::Dynamic(..) => Some(span),
+                _ => None,
             })
+            .next()
     }
 
     fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
index c1cf3522b5d9c1ac72f6864aece8d925bca656c7..e90c2ef5e4361090a863380935ca6b39981bd504 100644 (file)
@@ -58,7 +58,7 @@ pub enum MethodError<'tcx> {
 
     // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
     // forgotten to import a trait.
-    IllegalSizedBound(Vec<DefId>, bool),
+    IllegalSizedBound(Vec<DefId>, bool, Span),
 
     // Found a match, but the return type is wrong
     BadReturnType,
@@ -204,7 +204,7 @@ pub fn lookup_method(
         let result =
             self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
 
-        if result.illegal_sized_bound {
+        if let Some(span) = result.illegal_sized_bound {
             let mut needs_mut = false;
             if let ty::Ref(region, t_type, mutability) = self_ty.kind {
                 let trait_type = self
@@ -249,7 +249,7 @@ pub fn lookup_method(
                 _ => Vec::new(),
             };
 
-            return Err(IllegalSizedBound(candidates, needs_mut));
+            return Err(IllegalSizedBound(candidates, needs_mut, span));
         }
 
         Ok(result.callee)
index 490c69b55362bb82346c2655ed0c0ad1f571c806..789bac2705b07c2d61ce6c2facf22f5a59e0a184 100644 (file)
@@ -640,9 +640,10 @@ macro_rules! report_function {
                 err.emit();
             }
 
-            MethodError::IllegalSizedBound(candidates, needs_mut) => {
+            MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
                 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
                 let mut err = self.sess().struct_span_err(span, &msg);
+                err.span_label(bound_span, "this has a `Sized` requirement");
                 if !candidates.is_empty() {
                     let help = format!(
                         "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
index 99b243a077792eec0386b3186fd0a244d3f0fd69..f9b9b7dbd34bb7c46dadcd414bc00017930cd5bc 100644 (file)
@@ -1,6 +1,9 @@
 error: the `wait` method cannot be invoked on a trait object
   --> $DIR/issue-35976.rs:14:9
    |
+LL |         fn wait(&self) where Self: Sized;
+   |                                    ----- this has a `Sized` requirement
+...
 LL |     arg.wait();
    |         ^^^^
    |
index 9185eaa65c06d02a7f186b5a6604108614248105..37c20535229610f60879c7fe58763e0d164e9128 100644 (file)
@@ -3,6 +3,11 @@ error: the `min` method cannot be invoked on a trait object
    |
 LL |      t.min().unwrap()
    |        ^^^
+   | 
+  ::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL
+   |
+LL |         Self: Sized,
+   |               ----- this has a `Sized` requirement
    |
    = note: you need `&mut dyn std::iter::Iterator<Item = &u64>` instead of `&dyn std::iter::Iterator<Item = &u64>`
 
index 7e9a2316be2bf79e87141b24b5ca9d41513e7d1b..4cd2098eef256c651aade2aa6957afc67547ffc1 100644 (file)
@@ -1,6 +1,9 @@
 error: the `foo` method cannot be invoked on a trait object
   --> $DIR/by-value-trait-object-safety.rs:18:7
    |
+LL |     fn foo(self) -> String where Self: Sized;
+   |                                        ----- this has a `Sized` requirement
+...
 LL |     x.foo();
    |       ^^^