Skip to content

Commit a73d57b

Browse files
committed
Extract overlap_check_considering_specialization from insert
1 parent 40e82d9 commit a73d57b

File tree

1 file changed

+112
-96
lines changed

1 file changed

+112
-96
lines changed

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

Lines changed: 112 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -88,127 +88,143 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
8888
simplified_self: Option<SimplifiedType>,
8989
overlap_mode: OverlapMode,
9090
) -> Result<OverlapResult<'tcx>, OverlapError<'tcx>> {
91-
let mut last_lint = None;
92-
let mut replace_children = Vec::new();
93-
9491
debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);
9592

9693
let possible_siblings = match simplified_self {
9794
Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)),
9895
None => PotentialSiblings::Unfiltered(iter_children(self)),
9996
};
10097

101-
for possible_sibling in possible_siblings {
102-
debug!(
103-
"insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
104-
impl_def_id, simplified_self, possible_sibling,
105-
);
98+
let result = overlap_check_considering_specialization(
99+
tcx,
100+
impl_def_id,
101+
possible_siblings,
102+
overlap_mode,
103+
);
106104

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

151-
let last_lint_mut = &mut last_lint;
152-
let (le, ge) = traits::overlapping_impls(
111+
result
112+
}
113+
}
114+
115+
fn overlap_check_considering_specialization<'tcx>(
116+
tcx: TyCtxt<'tcx>,
117+
impl_def_id: DefId,
118+
possible_siblings: PotentialSiblings<impl Iterator<Item = DefId>, impl Iterator<Item = DefId>>,
119+
overlap_mode: OverlapMode,
120+
) -> Result<OverlapResult<'tcx>, OverlapError<'tcx>> {
121+
let mut last_lint = None;
122+
let mut replace_children = Vec::new();
123+
124+
for possible_sibling in possible_siblings {
125+
debug!("insert: impl_def_id={:?}, possible_sibling={:?}", impl_def_id, possible_sibling);
126+
127+
let create_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>| {
128+
let trait_ref = overlap.impl_header.trait_ref.unwrap();
129+
let self_ty = trait_ref.self_ty();
130+
131+
OverlapError {
132+
with_impl: possible_sibling,
133+
trait_ref,
134+
// Only report the `Self` type if it has at least
135+
// some outer concrete shell; otherwise, it's
136+
// not adding much information.
137+
self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
138+
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
139+
involves_placeholder: overlap.involves_placeholder,
140+
}
141+
};
142+
143+
let report_overlap_error = |overlap: traits::coherence::OverlapResult<'tcx>,
144+
last_lint: &mut _| {
145+
// Found overlap, but no specialization; error out or report future-compat warning.
146+
147+
// Do we *still* get overlap if we disable the future-incompatible modes?
148+
let should_err = traits::overlapping_impls(
153149
tcx,
154150
possible_sibling,
155151
impl_def_id,
156-
traits::SkipLeakCheck::Yes,
152+
traits::SkipLeakCheck::default(),
157153
overlap_mode,
158154
)
159-
.map_or(Ok((false, false)), |overlap| {
160-
if let Some(overlap_kind) =
161-
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
162-
{
163-
match overlap_kind {
164-
ty::ImplOverlapKind::Permitted { marker: _ } => {}
165-
ty::ImplOverlapKind::Issue33140 => {
166-
*last_lint_mut = Some(FutureCompatOverlapError {
167-
error: create_overlap_error(overlap),
168-
kind: FutureCompatOverlapErrorKind::Issue33140,
169-
});
170-
}
171-
}
155+
.is_some();
156+
157+
let error = create_overlap_error(overlap);
172158

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

176-
let le = tcx.specializes((impl_def_id, possible_sibling));
177-
let ge = tcx.specializes((possible_sibling, impl_def_id));
193+
return Ok((false, false));
194+
}
178195

179-
if le == ge { report_overlap_error(overlap, last_lint_mut) } else { Ok((le, ge)) }
180-
})?;
196+
let le = tcx.specializes((impl_def_id, possible_sibling));
197+
let ge = tcx.specializes((possible_sibling, impl_def_id));
181198

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

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

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

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

207-
// No overlap with any potential siblings, so add as a new sibling.
208-
debug!("placing as new sibling");
209-
self.insert_blindly(tcx, impl_def_id);
210-
Ok(OverlapResult::NoOverlap(last_lint))
223+
if !replace_children.is_empty() {
224+
return Ok(OverlapResult::SpecializeAll(replace_children));
211225
}
226+
227+
Ok(OverlapResult::NoOverlap(last_lint))
212228
}
213229

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

0 commit comments

Comments
 (0)