From 0626afbcd23d9ef2e14617c609dc47765af117e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Sat, 29 Sep 2018 15:13:08 +0100 Subject: [PATCH 1/6] First stab at fixing #54505 --- src/librustc_typeck/check/demand.rs | 54 ++++++++++++- src/test/ui/range/issue-54505-no-literals.rs | 85 ++++++++++++++++++++ src/test/ui/range/issue-54505-no-std.rs | 61 ++++++++++++++ src/test/ui/range/issue-54505.fixed | 53 ++++++++++++ src/test/ui/range/issue-54505.rs | 53 ++++++++++++ src/test/ui/range/issue-54505.stderr | 75 +++++++++++++++++ 6 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/range/issue-54505-no-literals.rs create mode 100644 src/test/ui/range/issue-54505-no-std.rs create mode 100644 src/test/ui/range/issue-54505.fixed create mode 100644 src/test/ui/range/issue-54505.rs create mode 100644 src/test/ui/range/issue-54505.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 71c78e7f87c..f53a8168548 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -310,9 +310,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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); @@ -374,6 +375,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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, diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs new file mode 100644 index 00000000000..57d1938aca8 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.rs @@ -0,0 +1,85 @@ +// 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 or the MIT license +// , 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) {} + + +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 } +} diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs new file mode 100644 index 00000000000..8e8793c1736 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -0,0 +1,61 @@ +// 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 or the MIT license +// , 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) {} + + +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) +} diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed new file mode 100644 index 00000000000..ef8ded0f7a3 --- /dev/null +++ b/src/test/ui/range/issue-54505.fixed @@ -0,0 +1,53 @@ +// 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 or the MIT license +// , 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) {} + + +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) +} diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs new file mode 100644 index 00000000000..b81c879a37e --- /dev/null +++ b/src/test/ui/range/issue-54505.rs @@ -0,0 +1,53 @@ +// 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 or the MIT license +// , 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) {} + + +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) +} diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr new file mode 100644 index 00000000000..5a59594ff50 --- /dev/null +++ b/src/test/ui/range/issue-54505.stderr @@ -0,0 +1,75 @@ +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`. From f7d35cc5a8ffcf74937e8c00586d97609b1095ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Mon, 1 Oct 2018 23:23:57 +0100 Subject: [PATCH 2/6] Fix range borrowing suggestions logic --- src/librustc_typeck/check/demand.rs | 54 +++++-- .../ui/range/issue-54505-no-literals.fixed | 85 ++++++++++ .../ui/range/issue-54505-no-literals.stderr | 147 ++++++++++++++++++ src/test/ui/range/issue-54505-no-std.rs | 5 +- src/test/ui/range/issue-54505-no-std.stderr | 79 ++++++++++ 5 files changed, 354 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/range/issue-54505-no-literals.fixed create mode 100644 src/test/ui/range/issue-54505-no-literals.stderr create mode 100644 src/test/ui/range/issue-54505-no-std.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index f53a8168548..e0577add61c 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -309,12 +309,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; 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(_, _, _) | - _ if self.is_range_literal(expr) => format!("({})", src), - _ => src, + let needs_parens = match expr.node { + // parenthesize if needed (Issue #46756) + hir::ExprKind::Cast(_, _) | + hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if self.is_range_literal(expr) => true, + _ => false, }; + let sugg_expr = if needs_parens { format!("({})", src) } else { src }; + if let Some(sugg) = self.can_use_as_ref(expr) { return Some(sugg); } @@ -380,8 +384,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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"]; + // we support `::std::ops::Range` and `::std::core::Range` prefixes + // (via split on "|") + let ops_path = ["{{root}}", "std|core", "ops"]; let is_range_path = |path: &Path| { let ident_names: Vec<_> = path.segments @@ -394,24 +399,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { preceding.len() == 3 && preceding.iter() .zip(ops_path.iter()) - .all(|(a, b)| a == b) + .all(|(seg, match_seg)| { + match_seg.split("|") + .into_iter() + .any(|ref spl_seg| seg == spl_seg) + }) } else { false } }; - match expr.node { - ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | - ExprKind::Path(QPath::Resolved(None, ref path)) => { - return is_range_path(&path); + let is_range_struct_snippet = |span: &Span| { + // Tell if expression span snippet looks like an explicit + // Range struct or new() call. This is to allow rejecting + // Ranges constructed with non-literals. + let source_map = self.tcx.sess.source_map(); + let end_point = source_map.end_point(*span); + + if let Ok(end_string) = source_map.span_to_snippet(end_point) { + end_string.ends_with("}") || end_string.ends_with(")") + } else { + false } + }; + + match expr.node { + // all built-in range literals but `..=` and `..` + // desugar to Structs, `..` desugars to its struct path + ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | + ExprKind::Path(QPath::Resolved(None, ref path)) => { + return is_range_path(&path) && !is_range_struct_snippet(&expr.span); + } + + // `..=` desugars into RangeInclusive::new(...) 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; + return is_range_path(&path) && calls_new && + !is_range_struct_snippet(&expr.span); } } } diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed new file mode 100644 index 00000000000..5be024dff53 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.fixed @@ -0,0 +1,85 @@ +// 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 or the MIT license +// , 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) {} + + +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 } +} diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr new file mode 100644 index 00000000000..a8be4de5f0e --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.stderr @@ -0,0 +1,147 @@ +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:26:16 + | +LL | take_range(std::ops::Range { start: 0, end: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::Range` + | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }` + | + = note: expected type `&_` + found type `std::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:31:16 + | +LL | take_range(::std::ops::Range { start: 0, end: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::Range` + | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }` + | + = note: expected type `&_` + found type `std::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:36:16 + | +LL | take_range(std::ops::RangeFrom { start: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFrom` + | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }` + | + = note: expected type `&_` + found type `std::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:41:16 + | +LL | take_range(::std::ops::RangeFrom { start: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFrom` + | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }` + | + = note: expected type `&_` + found type `std::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:46:16 + | +LL | take_range(std::ops::RangeFull {}); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFull` + | help: consider borrowing here: `&std::ops::RangeFull {}` + | + = note: expected type `&_` + found type `std::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:51:16 + | +LL | take_range(::std::ops::RangeFull {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFull` + | help: consider borrowing here: `&::std::ops::RangeFull {}` + | + = note: expected type `&_` + found type `std::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:56:16 + | +LL | take_range(std::ops::RangeInclusive::new(0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeInclusive` + | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)` + | + = note: expected type `&_` + found type `std::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:61:16 + | +LL | take_range(::std::ops::RangeInclusive::new(0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeInclusive` + | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)` + | + = note: expected type `&_` + found type `std::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:66:16 + | +LL | take_range(std::ops::RangeTo { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeTo` + | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:71:16 + | +LL | take_range(::std::ops::RangeTo { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeTo` + | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:76:16 + | +LL | take_range(std::ops::RangeToInclusive { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeToInclusive` + | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeToInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:81:16 + | +LL | take_range(::std::ops::RangeToInclusive { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeToInclusive` + | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeToInclusive<{integer}>` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index 8e8793c1736..0dadaecd7d8 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -8,9 +8,8 @@ // 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` +// error-pattern: `#[panic_handler]` function required, but not found +// error-pattern: language item required, but not found: `eh_personality` // Regression test for #54505 - range borrowing suggestion had diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr new file mode 100644 index 00000000000..035bc640658 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -0,0 +1,79 @@ +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:31:16 + | +LL | take_range(0..1); + | ^^^^ + | | + | expected reference, found struct `core::ops::Range` + | help: consider borrowing here: `&(0..1)` + | + = note: expected type `&_` + found type `core::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:36:16 + | +LL | take_range(1..); + | ^^^ + | | + | expected reference, found struct `core::ops::RangeFrom` + | help: consider borrowing here: `&(1..)` + | + = note: expected type `&_` + found type `core::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:41:16 + | +LL | take_range(..); + | ^^ + | | + | expected reference, found struct `core::ops::RangeFull` + | help: consider borrowing here: `&(..)` + | + = note: expected type `&_` + found type `core::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:46:16 + | +LL | take_range(0..=1); + | ^^^^^ + | | + | expected reference, found struct `core::ops::RangeInclusive` + | help: consider borrowing here: `&(0..=1)` + | + = note: expected type `&_` + found type `core::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:51:16 + | +LL | take_range(..5); + | ^^^ + | | + | expected reference, found struct `core::ops::RangeTo` + | help: consider borrowing here: `&(..5)` + | + = note: expected type `&_` + found type `core::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:56:16 + | +LL | take_range(..=42); + | ^^^^^ + | | + | expected reference, found struct `core::ops::RangeToInclusive` + | help: consider borrowing here: `&(..=42)` + | + = note: expected type `&_` + found type `core::ops::RangeToInclusive<{integer}>` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. From 87bf9e2056f8ee71c71e5f9c91afbc1fd965def8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Tue, 2 Oct 2018 22:10:04 +0100 Subject: [PATCH 3/6] Address review comments --- src/librustc_typeck/check/demand.rs | 61 ++++++++----------- .../ui/range/issue-54505-no-literals.fixed | 10 --- src/test/ui/range/issue-54505-no-literals.rs | 10 --- .../ui/range/issue-54505-no-literals.stderr | 24 ++++---- src/test/ui/range/issue-54505-no-std.rs | 10 --- src/test/ui/range/issue-54505-no-std.stderr | 12 ++-- src/test/ui/range/issue-54505.fixed | 10 --- src/test/ui/range/issue-54505.rs | 10 --- src/test/ui/range/issue-54505.stderr | 12 ++-- 9 files changed, 51 insertions(+), 108 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index e0577add61c..6eaeee5c0e2 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -317,7 +317,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ if self.is_range_literal(expr) => true, _ => false, }; - let sugg_expr = if needs_parens { format!("({})", src) } else { src }; + let sugg_expr = if needs_parens { + format!("({})", src) + } else { + src + }; if let Some(sugg) = self.can_use_as_ref(expr) { return Some(sugg); @@ -379,67 +383,56 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - // This function checks if the specified expression is a built-in range literal - // (See: librustc/hir/lowering.rs::LoweringContext::lower_expr() ) + /// This function checks if the specified expression is a built-in range literal. + /// (See: ``librustc::hir::lowering::LoweringContext::lower_expr()``). fn is_range_literal(&self, expr: &hir::Expr) -> bool { use hir::{Path, QPath, ExprKind, TyKind}; - // we support `::std::ops::Range` and `::std::core::Range` prefixes - // (via split on "|") - let ops_path = ["{{root}}", "std|core", "ops"]; - + // We support `::std::ops::Range` and `::core::ops::Range` prefixes let is_range_path = |path: &Path| { - let ident_names: Vec<_> = path.segments - .iter() - .map(|seg| seg.ident.as_str()) - .collect(); + let mut segs = path.segments.iter() + .map(|seg| seg.ident.as_str()); - if let Some((last, preceding)) = ident_names.split_last() { - last.starts_with("Range") && - preceding.len() == 3 && - preceding.iter() - .zip(ops_path.iter()) - .all(|(seg, match_seg)| { - match_seg.split("|") - .into_iter() - .any(|ref spl_seg| seg == spl_seg) - }) + if let (Some(root), Some(std_core), Some(ops), Some(range), None) = + (segs.next(), segs.next(), segs.next(), segs.next(), segs.next()) + { + // "{{root}}" is the equivalent of `::` prefix in Path + root == "{{root}}" && (std_core == "std" || std_core == "core") + && ops == "ops" && range.starts_with("Range") } else { false } }; - let is_range_struct_snippet = |span: &Span| { - // Tell if expression span snippet looks like an explicit - // Range struct or new() call. This is to allow rejecting - // Ranges constructed with non-literals. + let is_range_literal = |span: &Span| { + // Tell if expression span snippet doesn't look like an explicit + // Range struct or `new()` call. This is to allow inferring + // that this is a range literal. let source_map = self.tcx.sess.source_map(); let end_point = source_map.end_point(*span); if let Ok(end_string) = source_map.span_to_snippet(end_point) { - end_string.ends_with("}") || end_string.ends_with(")") + !(end_string.ends_with("}") || end_string.ends_with(")")) } else { false } - }; match expr.node { - // all built-in range literals but `..=` and `..` - // desugar to Structs, `..` desugars to its struct path + // All built-in range literals but `..=` and `..` desugar to Structs ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | + // `..` desugars to its struct path ExprKind::Path(QPath::Resolved(None, ref path)) => { - return is_range_path(&path) && !is_range_struct_snippet(&expr.span); + return is_range_path(&path) && is_range_literal(&expr.span); } - // `..=` desugars into RangeInclusive::new(...) + // `..=` desugars into `::std::ops::RangeInclusive::new(...)` 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"; + let call_to_new = segment.ident.as_str() == "new"; - return is_range_path(&path) && calls_new && - !is_range_struct_snippet(&expr.span); + return is_range_path(&path) && is_range_literal(&expr.span) && call_to_new; } } } diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed index 5be024dff53..4d8f67182b9 100644 --- a/src/test/ui/range/issue-54505-no-literals.fixed +++ b/src/test/ui/range/issue-54505-no-literals.fixed @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs index 57d1938aca8..dc21dcbc2db 100644 --- a/src/test/ui/range/issue-54505-no-literals.rs +++ b/src/test/ui/range/issue-54505-no-literals.rs @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr index a8be4de5f0e..b8811c98d21 100644 --- a/src/test/ui/range/issue-54505-no-literals.stderr +++ b/src/test/ui/range/issue-54505-no-literals.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:26:16 + --> $DIR/issue-54505-no-literals.rs:16:16 | LL | take_range(std::ops::Range { start: 0, end: 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | take_range(std::ops::Range { start: 0, end: 1 }); found type `std::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:31:16 + --> $DIR/issue-54505-no-literals.rs:21:16 | LL | take_range(::std::ops::Range { start: 0, end: 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | take_range(::std::ops::Range { start: 0, end: 1 }); found type `std::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:36:16 + --> $DIR/issue-54505-no-literals.rs:26:16 | LL | take_range(std::ops::RangeFrom { start: 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | take_range(std::ops::RangeFrom { start: 1 }); found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:41:16 + --> $DIR/issue-54505-no-literals.rs:31:16 | LL | take_range(::std::ops::RangeFrom { start: 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | take_range(::std::ops::RangeFrom { start: 1 }); found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:46:16 + --> $DIR/issue-54505-no-literals.rs:36:16 | LL | take_range(std::ops::RangeFull {}); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | take_range(std::ops::RangeFull {}); found type `std::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:51:16 + --> $DIR/issue-54505-no-literals.rs:41:16 | LL | take_range(::std::ops::RangeFull {}); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | take_range(::std::ops::RangeFull {}); found type `std::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:56:16 + --> $DIR/issue-54505-no-literals.rs:46:16 | LL | take_range(std::ops::RangeInclusive::new(0, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | take_range(std::ops::RangeInclusive::new(0, 1)); found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:61:16 + --> $DIR/issue-54505-no-literals.rs:51:16 | LL | take_range(::std::ops::RangeInclusive::new(0, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | take_range(::std::ops::RangeInclusive::new(0, 1)); found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:66:16 + --> $DIR/issue-54505-no-literals.rs:56:16 | LL | take_range(std::ops::RangeTo { end: 5 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | take_range(std::ops::RangeTo { end: 5 }); found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:71:16 + --> $DIR/issue-54505-no-literals.rs:61:16 | LL | take_range(::std::ops::RangeTo { end: 5 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | take_range(::std::ops::RangeTo { end: 5 }); found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:76:16 + --> $DIR/issue-54505-no-literals.rs:66:16 | LL | take_range(std::ops::RangeToInclusive { end: 5 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | take_range(std::ops::RangeToInclusive { end: 5 }); found type `std::ops::RangeToInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-literals.rs:81:16 + --> $DIR/issue-54505-no-literals.rs:71:16 | LL | take_range(::std::ops::RangeToInclusive { end: 5 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index 0dadaecd7d8..c2b17b53ba1 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern: `#[panic_handler]` function required, but not found // error-pattern: language item required, but not found: `eh_personality` diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr index 035bc640658..2810a3f076d 100644 --- a/src/test/ui/range/issue-54505-no-std.stderr +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -3,7 +3,7 @@ error: `#[panic_handler]` function required, but not found error: language item required, but not found: `eh_personality` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:31:16 + --> $DIR/issue-54505-no-std.rs:21:16 | LL | take_range(0..1); | ^^^^ @@ -15,7 +15,7 @@ LL | take_range(0..1); found type `core::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:36:16 + --> $DIR/issue-54505-no-std.rs:26:16 | LL | take_range(1..); | ^^^ @@ -27,7 +27,7 @@ LL | take_range(1..); found type `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:41:16 + --> $DIR/issue-54505-no-std.rs:31:16 | LL | take_range(..); | ^^ @@ -39,7 +39,7 @@ LL | take_range(..); found type `core::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:46:16 + --> $DIR/issue-54505-no-std.rs:36:16 | LL | take_range(0..=1); | ^^^^^ @@ -51,7 +51,7 @@ LL | take_range(0..=1); found type `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:51:16 + --> $DIR/issue-54505-no-std.rs:41:16 | LL | take_range(..5); | ^^^ @@ -63,7 +63,7 @@ LL | take_range(..5); found type `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:56:16 + --> $DIR/issue-54505-no-std.rs:46:16 | LL | take_range(..=42); | ^^^^^ diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed index ef8ded0f7a3..f8298c0b5ce 100644 --- a/src/test/ui/range/issue-54505.fixed +++ b/src/test/ui/range/issue-54505.fixed @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs index b81c879a37e..03673252dd3 100644 --- a/src/test/ui/range/issue-54505.rs +++ b/src/test/ui/range/issue-54505.rs @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr index 5a59594ff50..d6e1fb0cef2 100644 --- a/src/test/ui/range/issue-54505.stderr +++ b/src/test/ui/range/issue-54505.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-54505.rs:24:16 + --> $DIR/issue-54505.rs:14:16 | LL | take_range(0..1); | ^^^^ @@ -11,7 +11,7 @@ LL | take_range(0..1); found type `std::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505.rs:29:16 + --> $DIR/issue-54505.rs:19:16 | LL | take_range(1..); | ^^^ @@ -23,7 +23,7 @@ LL | take_range(1..); found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505.rs:34:16 + --> $DIR/issue-54505.rs:24:16 | LL | take_range(..); | ^^ @@ -35,7 +35,7 @@ LL | take_range(..); found type `std::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505.rs:39:16 + --> $DIR/issue-54505.rs:29:16 | LL | take_range(0..=1); | ^^^^^ @@ -47,7 +47,7 @@ LL | take_range(0..=1); found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505.rs:44:16 + --> $DIR/issue-54505.rs:34:16 | LL | take_range(..5); | ^^^ @@ -59,7 +59,7 @@ LL | take_range(..5); found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505.rs:49:16 + --> $DIR/issue-54505.rs:39:16 | LL | take_range(..=42); | ^^^^^ From 611e5c475106d41ee20847f8291594a708f0cbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Wed, 3 Oct 2018 08:08:14 +0100 Subject: [PATCH 4/6] Address review comments --- src/librustc_typeck/check/demand.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6eaeee5c0e2..85b6bcbd144 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } /// This function checks if the specified expression is a built-in range literal. - /// (See: ``librustc::hir::lowering::LoweringContext::lower_expr()``). + /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`). fn is_range_literal(&self, expr: &hir::Expr) -> bool { use hir::{Path, QPath, ExprKind, TyKind}; @@ -404,10 +404,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - let is_range_literal = |span: &Span| { - // Tell if expression span snippet doesn't look like an explicit - // Range struct or `new()` call. This is to allow inferring - // that this is a range literal. + let span_is_range_literal = |span: &Span| { + // Check whether a span corresponding to a range expression + // is a range literal, rather than an explicit struct or `new()` call. let source_map = self.tcx.sess.source_map(); let end_point = source_map.end_point(*span); @@ -423,7 +422,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | // `..` desugars to its struct path ExprKind::Path(QPath::Resolved(None, ref path)) => { - return is_range_path(&path) && is_range_literal(&expr.span); + return is_range_path(&path) && span_is_range_literal(&expr.span); } // `..=` desugars into `::std::ops::RangeInclusive::new(...)` @@ -432,7 +431,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node { let call_to_new = segment.ident.as_str() == "new"; - return is_range_path(&path) && is_range_literal(&expr.span) && call_to_new; + return is_range_path(&path) && span_is_range_literal(&expr.span) + && call_to_new; } } } From 882e373275a7ab540b0734a62e11836b4721ad94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Mon, 8 Oct 2018 18:39:09 +0200 Subject: [PATCH 5/6] Attempt to fix #54505 tests for wasm --- src/test/ui/range/issue-54505-no-std.rs | 7 +++++-- src/test/ui/range/issue-54505-no-std.stderr | 16 +++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index c2b17b53ba1..a6a49cc222e 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -1,6 +1,4 @@ // error-pattern: `#[panic_handler]` function required, but not found -// error-pattern: language item required, but not found: `eh_personality` - // Regression test for #54505 - range borrowing suggestion had // incorrect syntax (missing parentheses). @@ -9,9 +7,14 @@ // (so all Ranges resolve to core::ops::Range...) #![no_std] +#![feature(lang_items)] use core::ops::RangeBounds; +#[cfg(not(target_arch = "wasm32"))] +#[lang = "eh_personality"] +extern fn eh_personality() {} + // take a reference to any built-in range fn take_range(_r: &impl RangeBounds) {} diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr index 2810a3f076d..00eb9cda9c3 100644 --- a/src/test/ui/range/issue-54505-no-std.stderr +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -1,9 +1,7 @@ error: `#[panic_handler]` function required, but not found -error: language item required, but not found: `eh_personality` - error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:21:16 + --> $DIR/issue-54505-no-std.rs:24:16 | LL | take_range(0..1); | ^^^^ @@ -15,7 +13,7 @@ LL | take_range(0..1); found type `core::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:26:16 + --> $DIR/issue-54505-no-std.rs:29:16 | LL | take_range(1..); | ^^^ @@ -27,7 +25,7 @@ LL | take_range(1..); found type `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:31:16 + --> $DIR/issue-54505-no-std.rs:34:16 | LL | take_range(..); | ^^ @@ -39,7 +37,7 @@ LL | take_range(..); found type `core::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:36:16 + --> $DIR/issue-54505-no-std.rs:39:16 | LL | take_range(0..=1); | ^^^^^ @@ -51,7 +49,7 @@ LL | take_range(0..=1); found type `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:41:16 + --> $DIR/issue-54505-no-std.rs:44:16 | LL | take_range(..5); | ^^^ @@ -63,7 +61,7 @@ LL | take_range(..5); found type `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:46:16 + --> $DIR/issue-54505-no-std.rs:49:16 | LL | take_range(..=42); | ^^^^^ @@ -74,6 +72,6 @@ LL | take_range(..=42); = note: expected type `&_` found type `core::ops::RangeToInclusive<{integer}>` -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. From 1f7dafbb778dc9bff6a13828813fbcd105d977c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Tue, 9 Oct 2018 08:24:29 +0200 Subject: [PATCH 6/6] Fix test for windows os --- src/test/ui/range/issue-54505-no-std.rs | 4 ++++ src/test/ui/range/issue-54505-no-std.stderr | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index a6a49cc222e..1915fd82899 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -15,6 +15,10 @@ use core::ops::RangeBounds; #[lang = "eh_personality"] extern fn eh_personality() {} +#[cfg(target_os = "windows")] +#[lang = "eh_unwind_resume"] +extern fn eh_unwind_resume() {} + // take a reference to any built-in range fn take_range(_r: &impl RangeBounds) {} diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr index 00eb9cda9c3..4922e59953c 100644 --- a/src/test/ui/range/issue-54505-no-std.stderr +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -1,7 +1,7 @@ error: `#[panic_handler]` function required, but not found error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:24:16 + --> $DIR/issue-54505-no-std.rs:28:16 | LL | take_range(0..1); | ^^^^ @@ -13,7 +13,7 @@ LL | take_range(0..1); found type `core::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:29:16 + --> $DIR/issue-54505-no-std.rs:33:16 | LL | take_range(1..); | ^^^ @@ -25,7 +25,7 @@ LL | take_range(1..); found type `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:34:16 + --> $DIR/issue-54505-no-std.rs:38:16 | LL | take_range(..); | ^^ @@ -37,7 +37,7 @@ LL | take_range(..); found type `core::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:39:16 + --> $DIR/issue-54505-no-std.rs:43:16 | LL | take_range(0..=1); | ^^^^^ @@ -49,7 +49,7 @@ LL | take_range(0..=1); found type `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:44:16 + --> $DIR/issue-54505-no-std.rs:48:16 | LL | take_range(..5); | ^^^ @@ -61,7 +61,7 @@ LL | take_range(..5); found type `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:49:16 + --> $DIR/issue-54505-no-std.rs:53:16 | LL | take_range(..=42); | ^^^^^