return if token::ModSep == self.token.kind {
// We have some certainty that this was a bad turbofish at this point.
// `foo< bar >::`
- err.suggest_turbofish = Some(op.span.shrink_to_lo());
+ if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+ err.suggest_turbofish = Some(op.span.shrink_to_lo());
+ } else {
+ err.help_turbofish = Some(());
+ }
let snapshot = self.create_snapshot_for_diagnostic();
self.bump(); // `::`
} else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
// We have high certainty that this was a bad turbofish at this point.
// `foo< bar >(`
- err.suggest_turbofish = Some(op.span.shrink_to_lo());
+ if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+ err.suggest_turbofish = Some(op.span.shrink_to_lo());
+ } else {
+ err.help_turbofish = Some(());
+ }
// Consume the fn call arguments.
match self.consume_fn_args() {
Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)),
--- /dev/null
+error: comparison operators cannot be chained
+ --> $DIR/nested-bad-turbofish.rs:2:16
+ |
+LL | foo<<S as T>::V>();
+ | ^ ^
+ |
+ = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ = help: or use `(...)` if you meant to specify fn arguments
+
+error: aborting due to previous error
+