Skip to content

Commit f667937

Browse files
Don't run coherence twice for future-compat lints
1 parent e6ec0d1 commit f667937

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

src/librustc/traits/specialize/specialization_graph.rs

+43-30
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ impl<'tcx> Children {
8686
impl_def_id, simplified_self, possible_sibling,
8787
);
8888

89-
let overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
90-
// Found overlap, but no specialization; error out.
89+
let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
9190
let trait_ref = overlap.impl_header.trait_ref.unwrap();
9291
let self_ty = trait_ref.self_ty();
92+
9393
OverlapError {
9494
with_impl: possible_sibling,
9595
trait_desc: trait_ref.print_only_trait_path().to_string(),
@@ -106,21 +106,49 @@ impl<'tcx> Children {
106106
}
107107
};
108108

109-
let allowed_to_overlap =
110-
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling);
109+
let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
110+
last_lint: &mut _| {
111+
// Found overlap, but no specialization; error out or report future-compat warning.
112+
113+
// Do we *still* get overlap if we disable the future-incompatible modes?
114+
let should_err = traits::overlapping_impls(
115+
tcx,
116+
possible_sibling,
117+
impl_def_id,
118+
traits::SkipLeakCheck::default(),
119+
|_| true,
120+
|| false,
121+
);
122+
123+
let error = create_overlap_error(overlap);
124+
125+
if should_err {
126+
Err(error)
127+
} else {
128+
*last_lint = Some(FutureCompatOverlapError {
129+
error,
130+
kind: FutureCompatOverlapErrorKind::LeakCheck,
131+
});
132+
133+
Ok((false, false))
134+
}
135+
};
111136

137+
let last_lint_mut = &mut last_lint;
112138
let (le, ge) = traits::overlapping_impls(
113139
tcx,
114140
possible_sibling,
115141
impl_def_id,
116-
traits::SkipLeakCheck::default(),
142+
traits::SkipLeakCheck::Yes,
117143
|overlap| {
118-
if let Some(overlap_kind) = &allowed_to_overlap {
144+
if let Some(overlap_kind) =
145+
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
146+
{
119147
match overlap_kind {
120148
ty::ImplOverlapKind::Permitted { marker: _ } => {}
121149
ty::ImplOverlapKind::Issue33140 => {
122-
last_lint = Some(FutureCompatOverlapError {
123-
error: overlap_error(overlap),
150+
*last_lint_mut = Some(FutureCompatOverlapError {
151+
error: create_overlap_error(overlap),
124152
kind: FutureCompatOverlapErrorKind::Issue33140,
125153
});
126154
}
@@ -132,7 +160,11 @@ impl<'tcx> Children {
132160
let le = tcx.specializes((impl_def_id, possible_sibling));
133161
let ge = tcx.specializes((possible_sibling, impl_def_id));
134162

135-
if le == ge { Err(overlap_error(overlap)) } else { Ok((le, ge)) }
163+
if le == ge {
164+
report_overlap_error(overlap, last_lint_mut)
165+
} else {
166+
Ok((le, ge))
167+
}
136168
},
137169
|| Ok((false, false)),
138170
)?;
@@ -153,27 +185,8 @@ impl<'tcx> Children {
153185

154186
replace_children.push(possible_sibling);
155187
} else {
156-
if let None = allowed_to_overlap {
157-
// Do future-compat checks for overlap.
158-
159-
if last_lint.is_none() {
160-
traits::overlapping_impls(
161-
tcx,
162-
possible_sibling,
163-
impl_def_id,
164-
traits::SkipLeakCheck::Yes,
165-
|overlap| {
166-
last_lint = Some(FutureCompatOverlapError {
167-
error: overlap_error(overlap),
168-
kind: FutureCompatOverlapErrorKind::LeakCheck,
169-
});
170-
},
171-
|| (),
172-
);
173-
}
174-
}
175-
176-
// no overlap (error bailed already via ?)
188+
// Either there's no overlap, or the overlap was already reported by
189+
// `overlap_error`.
177190
}
178191
}
179192

0 commit comments

Comments
 (0)