if self.can_coerce(ref_ty, expected) {
if let Ok(src) = cm.span_to_snippet(sp) {
let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
- hir::ExprKind::Cast(_, _) |
- hir::ExprKind::Binary(_, _, _) => format!("({})", src),
- _ => src,
+ hir::ExprKind::Cast(_, _) |
+ hir::ExprKind::Binary(_, _, _) |
+ _ if self.is_range_literal(expr) => format!("({})", src),
+ _ => src,
};
if let Some(sugg) = self.can_use_as_ref(expr) {
return Some(sugg);
None
}
+ // This function checks if the specified expression is a built-in range literal
+ // (See: librustc/hir/lowering.rs::LoweringContext::lower_expr() )
+ fn is_range_literal(&self, expr: &hir::Expr) -> bool {
+ use hir::{Path, QPath, ExprKind, TyKind};
+
+ // TODO how to work out std vs core here?
+ let ops_path = ["{{root}}", "std", "ops"];
+
+ let is_range_path = |path: &Path| {
+ let ident_names: Vec<_> = path.segments
+ .iter()
+ .map(|seg| seg.ident.as_str())
+ .collect();
+
+ if let Some((last, preceding)) = ident_names.split_last() {
+ last.starts_with("Range") &&
+ preceding.len() == 3 &&
+ preceding.iter()
+ .zip(ops_path.iter())
+ .all(|(a, b)| a == b)
+ } else {
+ false
+ }
+ };
+
+ match expr.node {
+ ExprKind::Struct(QPath::Resolved(None, ref path), _, _) |
+ ExprKind::Path(QPath::Resolved(None, ref path)) => {
+ return is_range_path(&path);
+ }
+
+ ExprKind::Call(ref func, _) => {
+ if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
+ if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
+ let calls_new = segment.ident.as_str() == "new";
+
+ return is_range_path(&path) && calls_new;
+ }
+ }
+ }
+
+ _ => {}
+ }
+
+ false
+ }
+
pub fn check_for_cast(&self,
err: &mut DiagnosticBuilder<'tcx>,
expr: &hir::Expr,
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+ take_range(std::ops::Range { start: 0, end: 1 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+ take_range(::std::ops::Range { start: 0, end: 1 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+ take_range(std::ops::RangeFrom { start: 1 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+ take_range(::std::ops::RangeFrom { start: 1 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+ take_range(std::ops::RangeFull {});
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::RangeFull {}
+
+ take_range(::std::ops::RangeFull {});
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::RangeFull {}
+
+ take_range(std::ops::RangeInclusive::new(0, 1));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+ take_range(::std::ops::RangeInclusive::new(0, 1));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+ take_range(std::ops::RangeTo { end: 5 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+ take_range(::std::ops::RangeTo { end: 5 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+ take_range(std::ops::RangeToInclusive { end: 5 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+ take_range(::std::ops::RangeToInclusive { end: 5 });
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+// error-pattern: error: `#[panic_handler]` function required, but not found
+// error-pattern: language item required, but not found: `panic_info`
+
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+// This test doesn't use std
+// (so all Ranges resolve to core::ops::Range...)
+
+#![no_std]
+
+use core::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+ take_range(0..1);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..1)
+
+ take_range(1..);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(1..)
+
+ take_range(..);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..)
+
+ take_range(0..=1);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..=1)
+
+ take_range(..5);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..5)
+
+ take_range(..=42);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..=42)
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+ take_range(&(0..1));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..1)
+
+ take_range(&(1..));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(1..)
+
+ take_range(&(..));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..)
+
+ take_range(&(0..=1));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..=1)
+
+ take_range(&(..5));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..5)
+
+ take_range(&(..=42));
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..=42)
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+ take_range(0..1);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..1)
+
+ take_range(1..);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(1..)
+
+ take_range(..);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..)
+
+ take_range(0..=1);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(0..=1)
+
+ take_range(..5);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..5)
+
+ take_range(..=42);
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &(..=42)
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:24:16
+ |
+LL | take_range(0..1);
+ | ^^^^
+ | |
+ | expected reference, found struct `std::ops::Range`
+ | help: consider borrowing here: `&(0..1)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:29:16
+ |
+LL | take_range(1..);
+ | ^^^
+ | |
+ | expected reference, found struct `std::ops::RangeFrom`
+ | help: consider borrowing here: `&(1..)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:34:16
+ |
+LL | take_range(..);
+ | ^^
+ | |
+ | expected reference, found struct `std::ops::RangeFull`
+ | help: consider borrowing here: `&(..)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:39:16
+ |
+LL | take_range(0..=1);
+ | ^^^^^
+ | |
+ | expected reference, found struct `std::ops::RangeInclusive`
+ | help: consider borrowing here: `&(0..=1)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:44:16
+ |
+LL | take_range(..5);
+ | ^^^
+ | |
+ | expected reference, found struct `std::ops::RangeTo`
+ | help: consider borrowing here: `&(..5)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-54505.rs:49:16
+ |
+LL | take_range(..=42);
+ | ^^^^^
+ | |
+ | expected reference, found struct `std::ops::RangeToInclusive`
+ | help: consider borrowing here: `&(..=42)`
+ |
+ = note: expected type `&_`
+ found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.