Skip to content

Commit a2c2b27

Browse files
committed
Handle ambiguous projections
1 parent b528cc9 commit a2c2b27

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

clippy_lints/src/dereference.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
33
use clippy_utils::msrvs::{self, Msrv};
44
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
55
use clippy_utils::sugg::has_enclosing_paren;
6-
use clippy_utils::ty::{adt_and_variant_of_res, expr_sig, is_copy, peel_mid_ty_refs, ty_sig};
6+
use clippy_utils::ty::{adt_and_variant_of_res, expr_sig, implements_trait, is_copy, peel_mid_ty_refs, ty_sig};
77
use clippy_utils::{
88
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
99
};
@@ -1362,7 +1362,12 @@ fn replace_types<'tcx>(
13621362
let projection = cx.tcx
13631363
.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
13641364

1365-
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
1365+
// Verify that `new_ty` implements the relevant trait before trying to normalize `projection` to
1366+
// avoid hitting this `span_bug`:
1367+
// https://github.com/rust-lang/rust/blob/695072daa6cc04045f2aa79d751d884ad5263080/compiler/rustc_trait_selection/src/traits/query/normalize.rs#L272-L275
1368+
// See: https://github.com/rust-lang/rust/issues/107877
1369+
if implements_trait(cx, new_ty, assoc_item.container_id(cx.tcx), List::empty())
1370+
&& let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
13661371
&& substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
13671372
{
13681373
deque.push_back((*term_param_ty, projected_ty));

tests/ui/crashes/ice-rust-107877.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![allow(dead_code)]
2+
3+
struct Foo;
4+
5+
impl<'a> std::convert::TryFrom<&'a String> for Foo {
6+
type Error = std::convert::Infallible;
7+
8+
fn try_from(_: &'a String) -> Result<Self, Self::Error> {
9+
Ok(Foo)
10+
}
11+
}
12+
13+
fn find<E>(_: impl std::convert::TryInto<Foo, Error = E>) {}
14+
15+
fn main() {
16+
find(&String::new());
17+
}

0 commit comments

Comments
 (0)