Skip to content

Commit

Permalink
Expand where negative supertrait specific error is shown
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank authored and pietroalbini committed Mar 16, 2019
1 parent ad293f1 commit 363024d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 24 deletions.
52 changes: 28 additions & 24 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,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))
}
Expand Down Expand Up @@ -5502,6 +5502,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() ||
Expand Down Expand Up @@ -5546,9 +5547,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() {
Expand All @@ -5570,26 +5572,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();
}

Expand Down Expand Up @@ -5625,7 +5629,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()
};
Expand Down Expand Up @@ -6070,7 +6074,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),
Expand Down Expand Up @@ -7626,7 +7630,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)?;
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/issues/issue-58857.rs
Original file line number Diff line number Diff line change
@@ -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() {}
8 changes: 8 additions & 0 deletions src/test/ui/issues/issue-58857.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 363024d

Please sign in to comment.