Skip to content

Commit 83d1a1b

Browse files
authored
Rollup merge of #127596 - tesuji:help-unwrap-or, r=compiler-errors
More suggestion for converting `Option<&Vec<T>>` to `Option<&[T]>` Please review commit-by-commit.
2 parents 1e7ad4c + a776e5f commit 83d1a1b

File tree

3 files changed

+61
-15
lines changed

3 files changed

+61
-15
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+37-15
Original file line numberDiff line numberDiff line change
@@ -466,21 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
466466
borrow_removal_span,
467467
});
468468
return true;
469-
} else if let Some((deref_ty, _)) =
470-
self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1)
471-
&& self.can_eq(self.param_env, deref_ty, peeled)
472-
&& error_tys_equate_as_ref
473-
{
474-
let sugg = prefix_wrap(".as_deref()");
475-
err.subdiagnostic(errors::SuggestConvertViaMethod {
476-
span: expr.span.shrink_to_hi(),
477-
sugg,
478-
expected,
479-
found,
480-
borrow_removal_span,
481-
});
482-
return true;
483-
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
469+
} else if let ty::Ref(_, peeled_found_ty, _) = found_ty_inner.kind()
470+
&& let ty::Adt(adt, _) = peeled_found_ty.peel_refs().kind()
484471
&& self.tcx.is_lang_item(adt.did(), LangItem::String)
485472
&& peeled.is_str()
486473
// `Result::map`, conversely, does not take ref of the error type.
@@ -496,12 +483,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
496483
Applicability::MachineApplicable,
497484
);
498485
return true;
486+
} else {
487+
if !error_tys_equate_as_ref {
488+
return false;
489+
}
490+
let mut steps = self.autoderef(expr.span, found_ty_inner).silence_errors();
491+
if let Some((deref_ty, _)) = steps.nth(1)
492+
&& self.can_eq(self.param_env, deref_ty, peeled)
493+
{
494+
let sugg = prefix_wrap(".as_deref()");
495+
err.subdiagnostic(errors::SuggestConvertViaMethod {
496+
span: expr.span.shrink_to_hi(),
497+
sugg,
498+
expected,
499+
found,
500+
borrow_removal_span,
501+
});
502+
return true;
503+
}
504+
for (deref_ty, n_step) in steps {
505+
if self.can_eq(self.param_env, deref_ty, peeled) {
506+
let explicit_deref = "*".repeat(n_step);
507+
let sugg = prefix_wrap(&format!(".map(|v| &{explicit_deref}v)"));
508+
err.subdiagnostic(errors::SuggestConvertViaMethod {
509+
span: expr.span.shrink_to_hi(),
510+
sugg,
511+
expected,
512+
found,
513+
borrow_removal_span,
514+
});
515+
return true;
516+
}
517+
}
499518
}
500519
}
501520

502521
false
503522
}
504523

524+
/// If `ty` is `Option<T>`, returns `T, T, None`.
525+
/// If `ty` is `Result<T, E>`, returns `T, T, Some(E, E)`.
526+
/// Otherwise, returns `None`.
505527
fn deconstruct_option_or_result(
506528
&self,
507529
found_ty: Ty<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/127545>.
2+
#![crate_type = "lib"]
3+
4+
pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
5+
arg //~ ERROR 5:5: 5:8: mismatched types [E0308]
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/transforming-option-ref-issue-127545.rs:5:5
3+
|
4+
LL | pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
5+
| -------------- expected `Option<&[i32]>` because of return type
6+
LL | arg
7+
| ^^^ expected `Option<&[i32]>`, found `Option<&Vec<i32>>`
8+
|
9+
= note: expected enum `Option<&[i32]>`
10+
found enum `Option<&Vec<i32>>`
11+
help: try using `.map(|v| &**v)` to convert `Option<&Vec<i32>>` to `Option<&[i32]>`
12+
|
13+
LL | arg.map(|v| &**v)
14+
| ++++++++++++++
15+
16+
error: aborting due to 1 previous error
17+
18+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)