Recompute MissingConstructors
when needed
This only happens in a slow (diagnostics) path, so the code clarity gain is worth it.
This commit is contained in:
parent
b49f90760d
commit
c96bd28ab3
1 changed files with 56 additions and 39 deletions
|
@ -1285,7 +1285,9 @@ impl<'tcx> Constructor<'tcx> {
|
||||||
IntRange(range) => return range.to_pat(pcx.cx.tcx),
|
IntRange(range) => return range.to_pat(pcx.cx.tcx),
|
||||||
NonExhaustive => PatKind::Wild,
|
NonExhaustive => PatKind::Wild,
|
||||||
Opaque => bug!("we should not try to apply an opaque constructor"),
|
Opaque => bug!("we should not try to apply an opaque constructor"),
|
||||||
Wildcard => bug!("we should not try to apply a wildcard constructor"),
|
Wildcard => bug!(
|
||||||
|
"trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) }
|
Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) }
|
||||||
|
@ -1610,27 +1612,13 @@ impl<'tcx> Usefulness<'tcx> {
|
||||||
pcx: PatCtxt<'_, 'p, 'tcx>,
|
pcx: PatCtxt<'_, 'p, 'tcx>,
|
||||||
ctor: &Constructor<'tcx>,
|
ctor: &Constructor<'tcx>,
|
||||||
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
|
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
|
||||||
) -> Self {
|
is_top_level: bool,
|
||||||
match self {
|
|
||||||
UsefulWithWitness(witnesses) => UsefulWithWitness(
|
|
||||||
witnesses
|
|
||||||
.into_iter()
|
|
||||||
.map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
x => x,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_wildcard<'p>(
|
|
||||||
self,
|
|
||||||
pcx: PatCtxt<'_, 'p, 'tcx>,
|
|
||||||
missing_ctors: MissingConstructors<'tcx>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
match self {
|
match self {
|
||||||
UsefulWithWitness(witnesses) => {
|
UsefulWithWitness(witnesses) => {
|
||||||
let new_patterns = missing_ctors.report_patterns(pcx);
|
let new_witnesses = if ctor.is_wildcard() {
|
||||||
UsefulWithWitness(
|
let missing_ctors = MissingConstructors::new(pcx, is_top_level);
|
||||||
|
let new_patterns = missing_ctors.report_patterns(pcx);
|
||||||
witnesses
|
witnesses
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|witness| {
|
.flat_map(|witness| {
|
||||||
|
@ -1640,8 +1628,14 @@ impl<'tcx> Usefulness<'tcx> {
|
||||||
witness
|
witness
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect()
|
||||||
)
|
} else {
|
||||||
|
witnesses
|
||||||
|
.into_iter()
|
||||||
|
.map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns))
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
UsefulWithWitness(new_witnesses)
|
||||||
}
|
}
|
||||||
x => x,
|
x => x,
|
||||||
}
|
}
|
||||||
|
@ -2419,7 +2413,17 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
constructor
|
constructor
|
||||||
.split(pcx, Some(hir_id))
|
.split(pcx, Some(hir_id))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|c| is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard))
|
.map(|c| {
|
||||||
|
is_useful_specialized(
|
||||||
|
pcx,
|
||||||
|
v,
|
||||||
|
&c,
|
||||||
|
witness_preference,
|
||||||
|
hir_id,
|
||||||
|
is_under_guard,
|
||||||
|
is_top_level,
|
||||||
|
)
|
||||||
|
})
|
||||||
.find(|result| result.is_useful())
|
.find(|result| result.is_useful())
|
||||||
.unwrap_or(NotUseful)
|
.unwrap_or(NotUseful)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2446,20 +2450,31 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|ctor| ctor.split(pcx, None))
|
.flat_map(|ctor| ctor.split(pcx, None))
|
||||||
.map(|c| {
|
.map(|c| {
|
||||||
is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard)
|
is_useful_specialized(
|
||||||
|
pcx,
|
||||||
|
v,
|
||||||
|
&c,
|
||||||
|
witness_preference,
|
||||||
|
hir_id,
|
||||||
|
is_under_guard,
|
||||||
|
is_top_level,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.find(|result| result.is_useful())
|
.find(|result| result.is_useful())
|
||||||
.unwrap_or(NotUseful)
|
.unwrap_or(NotUseful)
|
||||||
} else {
|
} else {
|
||||||
let ctor_wild_subpatterns = Fields::empty();
|
// Some constructors are missing, thus we can specialize with the wildcard constructor,
|
||||||
let matrix = matrix.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns);
|
// which will stand for those constructors that are missing, and behaves like any of
|
||||||
// Unwrap is ok: v can always be specialized with its own constructor.
|
// them.
|
||||||
let v =
|
is_useful_specialized(
|
||||||
v.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns, true).unwrap();
|
pcx,
|
||||||
let usefulness =
|
v,
|
||||||
is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
|
constructor,
|
||||||
|
witness_preference,
|
||||||
usefulness.apply_wildcard(pcx, missing_ctors)
|
hir_id,
|
||||||
|
is_under_guard,
|
||||||
|
is_top_level,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
|
debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
|
||||||
|
@ -2471,20 +2486,22 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
fn is_useful_specialized<'p, 'tcx>(
|
fn is_useful_specialized<'p, 'tcx>(
|
||||||
pcx: PatCtxt<'_, 'p, 'tcx>,
|
pcx: PatCtxt<'_, 'p, 'tcx>,
|
||||||
v: &PatStack<'p, 'tcx>,
|
v: &PatStack<'p, 'tcx>,
|
||||||
ctor: Constructor<'tcx>,
|
ctor: &Constructor<'tcx>,
|
||||||
witness_preference: WitnessPreference,
|
witness_preference: WitnessPreference,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
is_under_guard: bool,
|
is_under_guard: bool,
|
||||||
|
is_top_level: bool,
|
||||||
) -> Usefulness<'tcx> {
|
) -> Usefulness<'tcx> {
|
||||||
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, pcx.ty);
|
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, pcx.ty);
|
||||||
|
|
||||||
// We cache the result of `Fields::wildcards` because it is used a lot.
|
// We cache the result of `Fields::wildcards` because it is used a lot.
|
||||||
let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
|
let ctor_wild_subpatterns = Fields::wildcards(pcx, ctor);
|
||||||
let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
|
let matrix = pcx.matrix.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns);
|
||||||
v.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns, true)
|
// Unwrap is ok: v can always be specialized with its own constructor.
|
||||||
.map(|v| is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false))
|
let v = v.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns, true).unwrap();
|
||||||
.map(|u| u.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns))
|
let usefulness =
|
||||||
.unwrap_or(NotUseful)
|
is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
|
||||||
|
usefulness.apply_constructor(pcx, ctor, &ctor_wild_subpatterns, is_top_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the constructor that the given pattern can be specialized to.
|
/// Determines the constructor that the given pattern can be specialized to.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue