about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-03-01 14:42:39 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-03-01 14:42:39 -0800
commitdc4973dfd918f5d71cd8e5c8e5aac5b8a86bf4e4 (patch)
tree7e2f269860f0c23ed538d7b5dbd2c8a2841befca
parentc1d2d83ca3b5155468ab96b09a7c54568449b137 (diff)
downloadrust-dc4973dfd918f5d71cd8e5c8e5aac5b8a86bf4e4.tar.gz
rust-dc4973dfd918f5d71cd8e5c8e5aac5b8a86bf4e4.zip
Expand where negative supertrait specific error is shown
Fix #58857.
-rw-r--r--src/libsyntax/parse/parser.rs52
-rw-r--r--src/test/ui/issues/issue-58857.rs7
-rw-r--r--src/test/ui/issues/issue-58857.stderr8
3 files changed, 43 insertions, 24 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fd5038a8614..1606bd591bd 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1803,7 +1803,7 @@ impl<'a> Parser<'a> {
         let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
         if parse_plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
-            bounds.append(&mut self.parse_generic_bounds(None)?);
+            bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
         }
         Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
     }
@@ -5523,6 +5523,7 @@ impl<'a> Parser<'a> {
         let mut bounds = Vec::new();
         let mut negative_bounds = Vec::new();
         let mut last_plus_span = None;
+        let mut was_negative = false;
         loop {
             // This needs to be synchronized with `Token::can_begin_bound`.
             let is_bound_start = self.check_path() || self.check_lifetime() ||
@@ -5567,9 +5568,10 @@ impl<'a> Parser<'a> {
                     }
                     let poly_span = lo.to(self.prev_span);
                     if is_negative {
-                        negative_bounds.push(
-                            last_plus_span.or(colon_span).unwrap()
-                                .to(poly_span));
+                        was_negative = true;
+                        if let Some(sp) = last_plus_span.or(colon_span) {
+                            negative_bounds.push(sp.to(poly_span));
+                        }
                     } else {
                         let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
                         let modifier = if question.is_some() {
@@ -5591,26 +5593,28 @@ impl<'a> Parser<'a> {
             }
         }
 
-        if !negative_bounds.is_empty() {
+        if !negative_bounds.is_empty() || was_negative {
             let plural = negative_bounds.len() > 1;
             let mut err = self.struct_span_err(negative_bounds,
                                                "negative trait bounds are not supported");
-            let bound_list = colon_span.unwrap().to(self.prev_span);
-            let mut new_bound_list = String::new();
-            if !bounds.is_empty() {
-                let mut snippets = bounds.iter().map(|bound| bound.span())
-                    .map(|span| self.sess.source_map().span_to_snippet(span));
-                while let Some(Ok(snippet)) = snippets.next() {
-                    new_bound_list.push_str(" + ");
-                    new_bound_list.push_str(&snippet);
-                }
-                new_bound_list = new_bound_list.replacen(" +", ":", 1);
-            }
-            err.span_suggestion_short(bound_list,
-                                      &format!("remove the trait bound{}",
-                                              if plural { "s" } else { "" }),
-                                      new_bound_list,
-                                      Applicability::MachineApplicable);
+            if let Some(bound_list) = colon_span {
+                let bound_list = bound_list.to(self.prev_span);
+                let mut new_bound_list = String::new();
+                if !bounds.is_empty() {
+                    let mut snippets = bounds.iter().map(|bound| bound.span())
+                        .map(|span| self.sess.source_map().span_to_snippet(span));
+                    while let Some(Ok(snippet)) = snippets.next() {
+                        new_bound_list.push_str(" + ");
+                        new_bound_list.push_str(&snippet);
+                    }
+                    new_bound_list = new_bound_list.replacen(" +", ":", 1);
+                }
+                err.span_suggestion_short(bound_list,
+                                        &format!("remove the trait bound{}",
+                                                if plural { "s" } else { "" }),
+                                        new_bound_list,
+                                        Applicability::MachineApplicable);
+            }
             err.emit();
         }
 
@@ -5646,7 +5650,7 @@ impl<'a> Parser<'a> {
 
         // Parse optional colon and param bounds.
         let bounds = if self.eat(&token::Colon) {
-            self.parse_generic_bounds(None)?
+            self.parse_generic_bounds(Some(self.prev_span))?
         } else {
             Vec::new()
         };
@@ -6091,7 +6095,7 @@ impl<'a> Parser<'a> {
                 // or with mandatory equality sign and the second type.
                 let ty = self.parse_ty()?;
                 if self.eat(&token::Colon) {
-                    let bounds = self.parse_generic_bounds(None)?;
+                    let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
                     where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
                         ast::WhereBoundPredicate {
                             span: lo.to(self.prev_span),
@@ -7643,7 +7647,7 @@ impl<'a> Parser<'a> {
         tps.where_clause = self.parse_where_clause()?;
         let alias = if existential {
             self.expect(&token::Colon)?;
-            let bounds = self.parse_generic_bounds(None)?;
+            let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
             AliasKind::Existential(bounds)
         } else {
             self.expect(&token::Eq)?;
diff --git a/src/test/ui/issues/issue-58857.rs b/src/test/ui/issues/issue-58857.rs
new file mode 100644
index 00000000000..392e4ea0c2e
--- /dev/null
+++ b/src/test/ui/issues/issue-58857.rs
@@ -0,0 +1,7 @@
+struct Conj<A> {a : A}
+trait Valid {}
+
+impl<A: !Valid> Conj<A>{}
+//~^ ERROR negative trait bounds are not supported
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58857.stderr b/src/test/ui/issues/issue-58857.stderr
new file mode 100644
index 00000000000..040e9eb8a65
--- /dev/null
+++ b/src/test/ui/issues/issue-58857.stderr
@@ -0,0 +1,8 @@
+error: negative trait bounds are not supported
+  --> $DIR/issue-58857.rs:4:7
+   |
+LL | impl<A: !Valid> Conj<A>{}
+   |       ^^^^^^^^ help: remove the trait bound
+
+error: aborting due to previous error
+