Skip to content

Commit 408c732

Browse files
committed
Extract overlap_check_considering_specialization from insert
1 parent ada058d commit 408c732

File tree

1 file changed

+113
-94
lines changed

1 file changed

+113
-94
lines changed

compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs

+113-94
Original file line numberDiff line numberDiff line change
@@ -92,122 +92,141 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
9292
simplified_self: Option<SimplifiedType>,
9393
overlap_mode: OverlapMode,
9494
) -> Result<OverlapResult<'tcx>, OverlapError<'tcx>> {
95-
let mut last_lint = None;
96-
let mut replace_children = Vec::new();
97-
9895
let possible_siblings = match simplified_self {
9996
Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)),
10097
None => PotentialSiblings::Unfiltered(iter_children(self)),
10198
};
10299

103-
for possible_sibling in possible_siblings {
104-
debug!(?possible_sibling);
105-
106-
let create_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>| {
107-
let trait_ref = overlap.impl_header.trait_ref.unwrap();
108-
let self_ty = trait_ref.self_ty();
109-
110-
OverlapError {
111-
with_impl: possible_sibling,
112-
trait_ref,
113-
// Only report the `Self` type if it has at least
114-
// some outer concrete shell; otherwise, it's
115-
// not adding much information.
116-
self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
117-
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
118-
involves_placeholder: overlap.involves_placeholder,
119-
}
120-
};
121-
122-
let report_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>,
123-
last_lint: &mut _| {
124-
// Found overlap, but no specialization; error out or report future-compat warning.
125-
126-
// Do we *still* get overlap if we disable the future-incompatible modes?
127-
let should_err = traits::overlapping_impls(
128-
tcx,
129-
possible_sibling,
130-
impl_def_id,
131-
traits::SkipLeakCheck::default(),
132-
overlap_mode,
133-
)
134-
.is_some();
135-
136-
let error = create_overlap_error(overlap);
137-
138-
if should_err {
139-
Err(error)
140-
} else {
141-
*last_lint = Some(FutureCompatOverlapError {
142-
error,
143-
kind: FutureCompatOverlapErrorKind::LeakCheck,
144-
});
145-
146-
Ok((false, false))
147-
}
148-
};
100+
let result = overlap_check_considering_specialization(
101+
tcx,
102+
impl_def_id,
103+
possible_siblings,
104+
overlap_mode,
105+
);
106+
107+
if let Ok(OverlapResult::NoOverlap(_)) = result {
108+
// No overlap with any potential siblings, so add as a new sibling.
109+
debug!("placing as new sibling");
110+
self.insert_blindly(tcx, impl_def_id);
111+
}
112+
113+
result
114+
}
115+
}
116+
117+
fn overlap_check_considering_specialization<'tcx>(
118+
tcx: TyCtxt<'tcx>,
119+
impl_def_id: DefId,
120+
possible_siblings: PotentialSiblings<impl Iterator<Item = DefId>, impl Iterator<Item = DefId>>,
121+
overlap_mode: OverlapMode,
122+
) -> Result<OverlapResult<'tcx>, OverlapError<'tcx>> {
123+
let mut last_lint = None;
124+
let mut replace_children = Vec::new();
125+
126+
for possible_sibling in possible_siblings {
127+
debug!(?possible_sibling);
128+
129+
let create_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>| {
130+
let trait_ref = overlap.impl_header.trait_ref.unwrap();
131+
let self_ty = trait_ref.self_ty();
132+
133+
OverlapError {
134+
with_impl: possible_sibling,
135+
trait_ref,
136+
// Only report the `Self` type if it has at least
137+
// some outer concrete shell; otherwise, it's
138+
// not adding much information.
139+
self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
140+
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
141+
involves_placeholder: overlap.involves_placeholder,
142+
}
143+
};
149144

150-
let last_lint_mut = &mut last_lint;
151-
let (le, ge) = traits::overlapping_impls(
145+
let report_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>,
146+
last_lint: &mut _| {
147+
// Found overlap, but no specialization; error out or report future-compat warning.
148+
149+
// Do we *still* get overlap if we disable the future-incompatible modes?
150+
let should_err = traits::overlapping_impls(
152151
tcx,
153152
possible_sibling,
154153
impl_def_id,
155-
traits::SkipLeakCheck::Yes,
154+
traits::SkipLeakCheck::default(),
156155
overlap_mode,
157156
)
158-
.map_or(Ok((false, false)), |overlap| {
159-
if let Some(overlap_kind) =
160-
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
161-
{
162-
match overlap_kind {
163-
ty::ImplOverlapKind::Permitted { marker: _ } => {}
164-
ty::ImplOverlapKind::Issue33140 => {
165-
*last_lint_mut = Some(FutureCompatOverlapError {
166-
error: create_overlap_error(overlap),
167-
kind: FutureCompatOverlapErrorKind::Issue33140,
168-
});
169-
}
170-
}
157+
.is_some();
158+
159+
let error = create_overlap_error(overlap);
171160

172-
return Ok((false, false));
161+
if should_err {
162+
Err(error)
163+
} else {
164+
*last_lint = Some(FutureCompatOverlapError {
165+
error,
166+
kind: FutureCompatOverlapErrorKind::LeakCheck,
167+
});
168+
169+
Ok((false, false))
170+
}
171+
};
172+
173+
let last_lint_mut = &mut last_lint;
174+
let (le, ge) = traits::overlapping_impls(
175+
tcx,
176+
possible_sibling,
177+
impl_def_id,
178+
traits::SkipLeakCheck::Yes,
179+
overlap_mode,
180+
)
181+
.map_or(Ok((false, false)), |overlap| {
182+
if let Some(overlap_kind) =
183+
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
184+
{
185+
match overlap_kind {
186+
ty::ImplOverlapKind::Permitted { marker: _ } => {}
187+
ty::ImplOverlapKind::Issue33140 => {
188+
*last_lint_mut = Some(FutureCompatOverlapError {
189+
error: create_overlap_error(overlap),
190+
kind: FutureCompatOverlapErrorKind::Issue33140,
191+
});
192+
}
173193
}
174194

175-
let le = tcx.specializes((impl_def_id, possible_sibling));
176-
let ge = tcx.specializes((possible_sibling, impl_def_id));
195+
return Ok((false, false));
196+
}
177197

178-
if le == ge { report_overlap_error(overlap, last_lint_mut) } else { Ok((le, ge)) }
179-
})?;
198+
let le = tcx.specializes((impl_def_id, possible_sibling));
199+
let ge = tcx.specializes((possible_sibling, impl_def_id));
180200

181-
if le && !ge {
182-
debug!(
183-
"descending as child of TraitRef {:?}",
184-
tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
185-
);
201+
if le == ge { report_overlap_error(overlap, last_lint_mut) } else { Ok((le, ge)) }
202+
})?;
186203

187-
// The impl specializes `possible_sibling`.
188-
return Ok(OverlapResult::SpecializeOne(possible_sibling));
189-
} else if ge && !le {
190-
debug!(
191-
"placing as parent of TraitRef {:?}",
192-
tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
193-
);
204+
if le && !ge {
205+
debug!(
206+
"descending as child of TraitRef {:?}",
207+
tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
208+
);
194209

195-
replace_children.push(possible_sibling);
196-
} else {
197-
// Either there's no overlap, or the overlap was already reported by
198-
// `overlap_error`.
199-
}
200-
}
210+
// The impl specializes `possible_sibling`.
211+
return Ok(OverlapResult::SpecializeOne(possible_sibling));
212+
} else if ge && !le {
213+
debug!(
214+
"placing as parent of TraitRef {:?}",
215+
tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
216+
);
201217

202-
if !replace_children.is_empty() {
203-
return Ok(OverlapResult::SpecializeAll(replace_children));
218+
replace_children.push(possible_sibling);
219+
} else {
220+
// Either there's no overlap, or the overlap was already reported by
221+
// `overlap_error`.
204222
}
223+
}
205224

206-
// No overlap with any potential siblings, so add as a new sibling.
207-
debug!("placing as new sibling");
208-
self.insert_blindly(tcx, impl_def_id);
209-
Ok(OverlapResult::NoOverlap(last_lint))
225+
if !replace_children.is_empty() {
226+
return Ok(OverlapResult::SpecializeAll(replace_children));
210227
}
228+
229+
Ok(OverlapResult::NoOverlap(last_lint))
211230
}
212231

213232
fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {

0 commit comments

Comments
 (0)