diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 78b16ffee81cf..e533ee78cc824 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -77,6 +77,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } false }; + + // Special case: range expressions are desugared to struct literals in HIR, + // so they would normally return `Unambiguous` precedence in expr.precedence. + // we should return `Range` precedence for correct parenthesization in suggestions. + if is_range_literal(expr) { + return ExprPrecedence::Range; + } + expr.precedence(&has_attr) } diff --git a/tests/ui/feature-gates/feature-gate-new_range.stderr b/tests/ui/feature-gates/feature-gate-new_range.stderr index c4241390418b6..b7f70d30bfa0b 100644 --- a/tests/ui/feature-gates/feature-gate-new_range.stderr +++ b/tests/ui/feature-gates/feature-gate-new_range.stderr @@ -10,8 +10,8 @@ LL | let a: core::range::RangeFrom = 1..; found struct `std::ops::RangeFrom<{integer}>` help: call `Into::into` on this expression to convert `std::ops::RangeFrom<{integer}>` into `std::range::RangeFrom` | -LL | let a: core::range::RangeFrom = 1...into(); - | +++++++ +LL | let a: core::range::RangeFrom = (1..).into(); + | + ++++++++ error[E0308]: mismatched types --> $DIR/feature-gate-new_range.rs:6:37 @@ -25,8 +25,8 @@ LL | let b: core::range::Range = 2..3; found struct `std::ops::Range<{integer}>` help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `std::range::Range` | -LL | let b: core::range::Range = 2..3.into(); - | +++++++ +LL | let b: core::range::Range = (2..3).into(); + | + ++++++++ error[E0308]: mismatched types --> $DIR/feature-gate-new_range.rs:8:46 @@ -40,8 +40,8 @@ LL | let c: core::range::RangeInclusive = 4..=5; found struct `std::ops::RangeInclusive<{integer}>` help: call `Into::into` on this expression to convert `std::ops::RangeInclusive<{integer}>` into `std::range::RangeInclusive` | -LL | let c: core::range::RangeInclusive = 4..=5.into(); - | +++++++ +LL | let c: core::range::RangeInclusive = (4..=5).into(); + | + ++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.fixed b/tests/ui/suggestions/into-convert-range-issue-148344.fixed new file mode 100644 index 0000000000000..5bf0e8e3063bf --- /dev/null +++ b/tests/ui/suggestions/into-convert-range-issue-148344.fixed @@ -0,0 +1,15 @@ +//@ run-rustfix +use std::ops::Range; + +struct Strange; +impl From> for Strange { + fn from(_: Range) -> Self { + Self + } +} + +fn main() { + let _: Strange = (0..10).into(); + //~^ ERROR mismatched types + //~| HELP call `Into::into` on this expression +} diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.rs b/tests/ui/suggestions/into-convert-range-issue-148344.rs new file mode 100644 index 0000000000000..aa1df2d4103ac --- /dev/null +++ b/tests/ui/suggestions/into-convert-range-issue-148344.rs @@ -0,0 +1,15 @@ +//@ run-rustfix +use std::ops::Range; + +struct Strange; +impl From> for Strange { + fn from(_: Range) -> Self { + Self + } +} + +fn main() { + let _: Strange = 0..10; + //~^ ERROR mismatched types + //~| HELP call `Into::into` on this expression +} diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.stderr b/tests/ui/suggestions/into-convert-range-issue-148344.stderr new file mode 100644 index 0000000000000..ce5342f5789b9 --- /dev/null +++ b/tests/ui/suggestions/into-convert-range-issue-148344.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/into-convert-range-issue-148344.rs:12:22 + | +LL | let _: Strange = 0..10; + | ------- ^^^^^ expected `Strange`, found `Range<{integer}>` + | | + | expected due to this + | + = note: expected struct `Strange` + found struct `std::ops::Range<{integer}>` +help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `Strange` + | +LL | let _: Strange = (0..10).into(); + | + ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.