Rollup merge of #73639 - ayazhafiz:i/73553, r=davidtwco

Change heuristic for determining range literal

Currently, rustc uses a heuristic to determine if a range expression is
not a literal based on whether the expression looks like a function call
or struct initialization. This fails for range literals whose
lower/upper bounds are the results of function calls. A possibly-better
heuristic is to check if the expression contains `..`, required in range
literals.

Of course, this is also not perfect; for example, if the range
expression is a struct which includes some text with `..` this will
fail, but in general I believe it is a better heuristic.

A better alternative altogether is to add the `QPath::LangItem` enum
variant suggested in #60607. I would be happy to do this as a precursor
to this patch if someone is able to provide general suggestions on how
usages of `QPath` need to be changed later in the compiler with the
`LangItem` variant.

Closes #73553
This commit is contained in:
Dylan DPC 2020-06-24 14:28:39 +02:00 committed by GitHub
commit 1d1c400324
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 7 deletions

View File

@ -1511,13 +1511,7 @@ pub fn is_range_literal(sm: &SourceMap, expr: &Expr<'_>) -> bool {
// Check whether a span corresponding to a range expression is a
// range literal, rather than an explicit struct or `new()` call.
fn is_lit(sm: &SourceMap, span: &Span) -> bool {
let end_point = sm.end_point(*span);
if let Ok(end_string) = sm.span_to_snippet(end_point) {
!(end_string.ends_with('}') || end_string.ends_with(')'))
} else {
false
}
sm.span_to_snippet(*span).map(|range_src| range_src.contains("..")).unwrap_or(false)
};
match expr.kind {

View File

@ -0,0 +1,16 @@
type Range = std::ops::Range<usize>;
fn demo(r: &Range) {
println!("{:?}", r);
}
fn tell(x: usize) -> usize {
x
}
fn main() {
demo(tell(1)..tell(10));
//~^ ERROR mismatched types
demo(1..10);
//~^ ERROR mismatched types
}

View File

@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> $DIR/issue-73553-misinterp-range-literal.rs:12:10
|
LL | demo(tell(1)..tell(10));
| ^^^^^^^^^^^^^^^^^
| |
| expected reference, found struct `std::ops::Range`
| help: consider borrowing here: `&(tell(1)..tell(10))`
|
= note: expected reference `&std::ops::Range<usize>`
found struct `std::ops::Range<usize>`
error[E0308]: mismatched types
--> $DIR/issue-73553-misinterp-range-literal.rs:14:10
|
LL | demo(1..10);
| ^^^^^
| |
| expected reference, found struct `std::ops::Range`
| help: consider borrowing here: `&(1..10)`
|
= note: expected reference `&std::ops::Range<usize>`
found struct `std::ops::Range<{integer}>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.