Auto merge of #121469 - matthiaskrgr:rollup-oaoxuo2, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #120598 (No need to `validate_alias_bound_self_from_param_env` in `assemble_alias_bound_candidates`) - #121386 (test that we do not support higher-ranked regions in opaque type inference) - #121393 (match lowering: Introduce a `TestCase` enum to replace most matching on `PatKind`) - #121401 (Fix typo in serialized.rs) - #121427 (Fix panic when compiling `Rocket`.) - #121439 (Fix typo in metadata.rs doc comment) - #121441 (`DefId` to `LocalDefId`) - #121452 (Add new maintainers to nto-qnx.md) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d9ae43c787
36 changed files with 688 additions and 483 deletions
|
@ -153,12 +153,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
|
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
|
||||||
if prev.ty != ty {
|
if prev.ty != ty {
|
||||||
let guar = ty.error_reported().err().unwrap_or_else(|| {
|
let guar = ty.error_reported().err().unwrap_or_else(|| {
|
||||||
prev.report_mismatch(
|
let (Ok(e) | Err(e)) = prev
|
||||||
&OpaqueHiddenType { ty, span: concrete_type.span },
|
.build_mismatch_error(
|
||||||
opaque_type_key.def_id,
|
&OpaqueHiddenType { ty, span: concrete_type.span },
|
||||||
infcx.tcx,
|
opaque_type_key.def_id,
|
||||||
)
|
infcx.tcx,
|
||||||
.emit()
|
)
|
||||||
|
.map(|d| d.emit());
|
||||||
|
e
|
||||||
});
|
});
|
||||||
prev.ty = Ty::new_error(infcx.tcx, guar);
|
prev.ty = Ty::new_error(infcx.tcx, guar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,7 +510,7 @@ impl server::FreeFunctions for Rustc<'_, '_> {
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) {
|
fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) {
|
||||||
let message = rustc_errors::DiagnosticMessage::from(diagnostic.message);
|
let message = rustc_errors::DiagnosticMessage::from(diagnostic.message);
|
||||||
let mut diag: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed> =
|
let mut diag: DiagnosticBuilder<'_, ()> =
|
||||||
DiagnosticBuilder::new(&self.sess().dcx, diagnostic.level.to_internal(), message);
|
DiagnosticBuilder::new(&self.sess().dcx, diagnostic.level.to_internal(), message);
|
||||||
diag.span(MultiSpan::from_spans(diagnostic.spans));
|
diag.span(MultiSpan::from_spans(diagnostic.spans));
|
||||||
for child in diagnostic.children {
|
for child in diagnostic.children {
|
||||||
|
|
|
@ -477,7 +477,7 @@ fn sanity_check_found_hidden_type<'tcx>(
|
||||||
} else {
|
} else {
|
||||||
let span = tcx.def_span(key.def_id);
|
let span = tcx.def_span(key.def_id);
|
||||||
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
|
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
|
||||||
Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
|
Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1027,7 +1027,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
||||||
let repr = if is_anonymous {
|
let repr = if is_anonymous {
|
||||||
tcx.adt_def(tcx.local_parent(def_id)).repr()
|
tcx.adt_def(tcx.local_parent(def_id)).repr()
|
||||||
} else {
|
} else {
|
||||||
tcx.repr_options_of_def(def_id.to_def_id())
|
tcx.repr_options_of_def(def_id)
|
||||||
};
|
};
|
||||||
let (kind, variants) = match &item.kind {
|
let (kind, variants) = match &item.kind {
|
||||||
ItemKind::Enum(def, _) => {
|
ItemKind::Enum(def, _) => {
|
||||||
|
|
|
@ -58,10 +58,10 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
|
||||||
// Only check against typeck if we didn't already error
|
// Only check against typeck if we didn't already error
|
||||||
if !hidden.ty.references_error() {
|
if !hidden.ty.references_error() {
|
||||||
for concrete_type in locator.typeck_types {
|
for concrete_type in locator.typeck_types {
|
||||||
if concrete_type.ty != tcx.erase_regions(hidden.ty)
|
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||||
&& !(concrete_type, hidden).references_error()
|
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||||
{
|
d.emit();
|
||||||
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,10 +134,10 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
|
||||||
// Only check against typeck if we didn't already error
|
// Only check against typeck if we didn't already error
|
||||||
if !hidden.ty.references_error() {
|
if !hidden.ty.references_error() {
|
||||||
for concrete_type in locator.typeck_types {
|
for concrete_type in locator.typeck_types {
|
||||||
if concrete_type.ty != tcx.erase_regions(hidden.ty)
|
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||||
&& !(concrete_type, hidden).references_error()
|
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||||
{
|
d.emit();
|
||||||
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,8 +287,10 @@ impl TaitConstraintLocator<'_> {
|
||||||
if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
|
if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
|
||||||
debug!(?concrete_type, "found constraint");
|
debug!(?concrete_type, "found constraint");
|
||||||
if let Some(prev) = &mut self.found {
|
if let Some(prev) = &mut self.found {
|
||||||
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
if concrete_type.ty != prev.ty {
|
||||||
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
|
let (Ok(guar) | Err(guar)) = prev
|
||||||
|
.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
|
||||||
|
.map(|d| d.emit());
|
||||||
prev.ty = Ty::new_error(self.tcx, guar);
|
prev.ty = Ty::new_error(self.tcx, guar);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -361,11 +363,13 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
||||||
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
|
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
|
||||||
);
|
);
|
||||||
if let Some(prev) = &mut hir_opaque_ty {
|
if let Some(prev) = &mut hir_opaque_ty {
|
||||||
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
if concrete_type.ty != prev.ty {
|
||||||
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
|
if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||||
tcx.def_span(opaque_type_key.def_id),
|
d.stash(
|
||||||
StashKey::OpaqueHiddenTypeMismatch,
|
tcx.def_span(opaque_type_key.def_id),
|
||||||
);
|
StashKey::OpaqueHiddenTypeMismatch,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hir_opaque_ty = Some(concrete_type);
|
hir_opaque_ty = Some(concrete_type);
|
||||||
|
@ -436,9 +440,12 @@ impl RpitConstraintChecker<'_> {
|
||||||
|
|
||||||
debug!(?concrete_type, "found constraint");
|
debug!(?concrete_type, "found constraint");
|
||||||
|
|
||||||
if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
|
if concrete_type.ty != self.found.ty {
|
||||||
{
|
if let Ok(d) =
|
||||||
self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
|
self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
|
||||||
|
{
|
||||||
|
d.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,12 +589,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
&& last_opaque_ty.ty != hidden_type.ty
|
&& last_opaque_ty.ty != hidden_type.ty
|
||||||
{
|
{
|
||||||
assert!(!self.fcx.next_trait_solver());
|
assert!(!self.fcx.next_trait_solver());
|
||||||
hidden_type
|
if let Ok(d) = hidden_type.build_mismatch_error(
|
||||||
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
|
&last_opaque_ty,
|
||||||
.stash(
|
opaque_type_key.def_id,
|
||||||
|
self.tcx(),
|
||||||
|
) {
|
||||||
|
d.stash(
|
||||||
self.tcx().def_span(opaque_type_key.def_id),
|
self.tcx().def_span(opaque_type_key.def_id),
|
||||||
StashKey::OpaqueHiddenTypeMismatch,
|
StashKey::OpaqueHiddenTypeMismatch,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -840,12 +840,12 @@ pub struct OpaqueHiddenType<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> OpaqueHiddenType<'tcx> {
|
impl<'tcx> OpaqueHiddenType<'tcx> {
|
||||||
pub fn report_mismatch(
|
pub fn build_mismatch_error(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
opaque_def_id: LocalDefId,
|
opaque_def_id: LocalDefId,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx> {
|
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
|
||||||
if let Some(diag) = tcx
|
if let Some(diag) = tcx
|
||||||
.sess
|
.sess
|
||||||
.dcx()
|
.dcx()
|
||||||
|
@ -853,18 +853,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
|
||||||
{
|
{
|
||||||
diag.cancel();
|
diag.cancel();
|
||||||
}
|
}
|
||||||
|
(self.ty, other.ty).error_reported()?;
|
||||||
// Found different concrete types for the opaque type.
|
// Found different concrete types for the opaque type.
|
||||||
let sub_diag = if self.span == other.span {
|
let sub_diag = if self.span == other.span {
|
||||||
TypeMismatchReason::ConflictType { span: self.span }
|
TypeMismatchReason::ConflictType { span: self.span }
|
||||||
} else {
|
} else {
|
||||||
TypeMismatchReason::PreviousUse { span: self.span }
|
TypeMismatchReason::PreviousUse { span: self.span }
|
||||||
};
|
};
|
||||||
tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
||||||
self_ty: self.ty,
|
self_ty: self.ty,
|
||||||
other_ty: other.ty,
|
other_ty: other.ty,
|
||||||
other_span: other.span,
|
other_span: other.span,
|
||||||
sub: sub_diag,
|
sub: sub_diag,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx), ret)]
|
#[instrument(level = "debug", skip(tcx), ret)]
|
||||||
|
@ -1471,7 +1472,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
.filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
|
.filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repr_options_of_def(self, did: DefId) -> ReprOptions {
|
pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions {
|
||||||
let mut flags = ReprFlags::empty();
|
let mut flags = ReprFlags::empty();
|
||||||
let mut size = None;
|
let mut size = None;
|
||||||
let mut max_align: Option<Align> = None;
|
let mut max_align: Option<Align> = None;
|
||||||
|
@ -1479,7 +1480,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
// Generate a deterministically-derived seed from the item's path hash
|
// Generate a deterministically-derived seed from the item's path hash
|
||||||
// to allow for cross-crate compilation to actually work
|
// to allow for cross-crate compilation to actually work
|
||||||
let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash().as_u64();
|
let mut field_shuffle_seed =
|
||||||
|
self.def_path_hash(did.to_def_id()).0.to_smaller_hash().as_u64();
|
||||||
|
|
||||||
// If the user defined a custom seed for layout randomization, xor the item's
|
// If the user defined a custom seed for layout randomization, xor the item's
|
||||||
// path hash with the user defined seed, this will allowing determinism while
|
// path hash with the user defined seed, this will allowing determinism while
|
||||||
|
|
|
@ -16,7 +16,7 @@ use rustc_data_structures::{
|
||||||
};
|
};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::{self, *};
|
||||||
use rustc_middle::thir::{self, *};
|
use rustc_middle::thir::{self, *};
|
||||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
|
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
@ -1052,18 +1052,31 @@ struct Ascription<'tcx> {
|
||||||
variance: ty::Variance,
|
variance: ty::Variance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum TestCase<'pat, 'tcx> {
|
||||||
|
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
|
||||||
|
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
|
||||||
|
Constant { value: mir::Const<'tcx> },
|
||||||
|
Range(&'pat PatRange<'tcx>),
|
||||||
|
Slice { len: usize, variable_length: bool },
|
||||||
|
Or,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct MatchPair<'pat, 'tcx> {
|
pub(crate) struct MatchPair<'pat, 'tcx> {
|
||||||
// This place...
|
/// This place...
|
||||||
place: PlaceBuilder<'tcx>,
|
place: PlaceBuilder<'tcx>,
|
||||||
|
|
||||||
// ... must match this pattern.
|
/// ... must pass this test...
|
||||||
// Invariant: after creation and simplification in `Candidate::new()`, all match pairs must be
|
// Invariant: after creation and simplification in `Candidate::new()`, this must not be
|
||||||
// simplified, i.e. require a test.
|
// `Irrefutable`.
|
||||||
pattern: &'pat Pat<'tcx>,
|
test_case: TestCase<'pat, 'tcx>,
|
||||||
|
|
||||||
/// Precomputed sub-match pairs of `pattern`.
|
/// ... and these subpairs must match.
|
||||||
subpairs: Vec<Self>,
|
subpairs: Vec<Self>,
|
||||||
|
|
||||||
|
/// The pattern this was created from.
|
||||||
|
pattern: &'pat Pat<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`Test`] for more.
|
/// See [`Test`] for more.
|
||||||
|
|
|
@ -13,11 +13,9 @@
|
||||||
//! testing a value against a constant.
|
//! testing a value against a constant.
|
||||||
|
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::expr::as_place::PlaceBuilder;
|
||||||
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
|
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair, TestCase};
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_middle::thir::{Pat, PatKind};
|
||||||
use rustc_middle::thir::{self, *};
|
|
||||||
use rustc_middle::ty;
|
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -62,13 +60,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let mut simplified_match_pairs = Vec::new();
|
let mut simplified_match_pairs = Vec::new();
|
||||||
// Repeatedly simplify match pairs until we're left with only unsimplifiable ones.
|
// Repeatedly simplify match pairs until we're left with only unsimplifiable ones.
|
||||||
loop {
|
loop {
|
||||||
for match_pair in mem::take(match_pairs) {
|
for mut match_pair in mem::take(match_pairs) {
|
||||||
if let Err(match_pair) = self.simplify_match_pair(
|
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
|
||||||
match_pair,
|
if let Some(binding) = binding {
|
||||||
candidate_bindings,
|
candidate_bindings.push(binding);
|
||||||
candidate_ascriptions,
|
}
|
||||||
match_pairs,
|
if let Some(ascription) = ascription {
|
||||||
) {
|
candidate_ascriptions.push(ascription);
|
||||||
|
}
|
||||||
|
// Simplifiable pattern; we replace it with its subpairs and simplify further.
|
||||||
|
match_pairs.append(&mut match_pair.subpairs);
|
||||||
|
} else {
|
||||||
|
// Unsimplifiable pattern; we recursively simplify its subpairs and don't
|
||||||
|
// process it further.
|
||||||
|
self.simplify_match_pairs(
|
||||||
|
&mut match_pair.subpairs,
|
||||||
|
candidate_bindings,
|
||||||
|
candidate_ascriptions,
|
||||||
|
);
|
||||||
simplified_match_pairs.push(match_pair);
|
simplified_match_pairs.push(match_pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,133 +126,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to simplify `match_pair`, returning `Ok(())` if successful. If successful, new match
|
|
||||||
/// pairs and bindings will have been pushed into the respective `Vec`s. If no simplification is
|
|
||||||
/// possible, `Err` is returned.
|
|
||||||
fn simplify_match_pair<'pat>(
|
|
||||||
&mut self,
|
|
||||||
mut match_pair: MatchPair<'pat, 'tcx>,
|
|
||||||
bindings: &mut Vec<Binding<'tcx>>,
|
|
||||||
ascriptions: &mut Vec<Ascription<'tcx>>,
|
|
||||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
|
||||||
) -> Result<(), MatchPair<'pat, 'tcx>> {
|
|
||||||
match match_pair.pattern.kind {
|
|
||||||
PatKind::Leaf { .. }
|
|
||||||
| PatKind::Deref { .. }
|
|
||||||
| PatKind::Array { .. }
|
|
||||||
| PatKind::Never
|
|
||||||
| PatKind::Wild
|
|
||||||
| PatKind::Error(_) => {}
|
|
||||||
|
|
||||||
PatKind::AscribeUserType {
|
|
||||||
ascription: thir::Ascription { ref annotation, variance },
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// Apply the type ascription to the value at `match_pair.place`
|
|
||||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
|
||||||
ascriptions.push(Ascription {
|
|
||||||
annotation: annotation.clone(),
|
|
||||||
source,
|
|
||||||
variance,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Binding {
|
|
||||||
name: _,
|
|
||||||
mutability: _,
|
|
||||||
mode,
|
|
||||||
var,
|
|
||||||
ty: _,
|
|
||||||
subpattern: _,
|
|
||||||
is_primary: _,
|
|
||||||
} => {
|
|
||||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
|
||||||
bindings.push(Binding {
|
|
||||||
span: match_pair.pattern.span,
|
|
||||||
source,
|
|
||||||
var_id: var,
|
|
||||||
binding_mode: mode,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::InlineConstant { subpattern: ref pattern, def } => {
|
|
||||||
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
|
||||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
|
||||||
let span = match_pair.pattern.span;
|
|
||||||
let parent_id = self.tcx.typeck_root_def_id(self.def_id.to_def_id());
|
|
||||||
let args = ty::InlineConstArgs::new(
|
|
||||||
self.tcx,
|
|
||||||
ty::InlineConstArgsParts {
|
|
||||||
parent_args: ty::GenericArgs::identity_for_item(self.tcx, parent_id),
|
|
||||||
ty: self.infcx.next_ty_var(TypeVariableOrigin {
|
|
||||||
kind: TypeVariableOriginKind::MiscVariable,
|
|
||||||
span,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.args;
|
|
||||||
let user_ty =
|
|
||||||
self.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
|
|
||||||
def.to_def_id(),
|
|
||||||
ty::UserArgs { args, user_self_ty: None },
|
|
||||||
));
|
|
||||||
let annotation = ty::CanonicalUserTypeAnnotation {
|
|
||||||
inferred_ty: pattern.ty,
|
|
||||||
span,
|
|
||||||
user_ty: Box::new(user_ty),
|
|
||||||
};
|
|
||||||
ascriptions.push(Ascription {
|
|
||||||
annotation,
|
|
||||||
source,
|
|
||||||
variance: ty::Contravariant,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Constant { .. } => {
|
|
||||||
// FIXME normalize patterns when possible
|
|
||||||
return Err(match_pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Range(ref range) => {
|
|
||||||
if range.is_full_range(self.tcx) != Some(true) {
|
|
||||||
return Err(match_pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
|
||||||
if !(prefix.is_empty() && slice.is_some() && suffix.is_empty()) {
|
|
||||||
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
|
|
||||||
return Err(match_pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Variant { adt_def, args, variant_index, subpatterns: _ } => {
|
|
||||||
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
|
|
||||||
i == variant_index || {
|
|
||||||
(self.tcx.features().exhaustive_patterns
|
|
||||||
|| self.tcx.features().min_exhaustive_patterns)
|
|
||||||
&& !v
|
|
||||||
.inhabited_predicate(self.tcx, adt_def)
|
|
||||||
.instantiate(self.tcx, args)
|
|
||||||
.apply_ignore_module(self.tcx, self.param_env)
|
|
||||||
}
|
|
||||||
}) && (adt_def.did().is_local()
|
|
||||||
|| !adt_def.is_variant_list_non_exhaustive());
|
|
||||||
if !irrefutable {
|
|
||||||
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
|
|
||||||
return Err(match_pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Or { .. } => return Err(match_pair),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simplifiable pattern; we replace it with its subpairs.
|
|
||||||
match_pairs.append(&mut match_pair.subpairs);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// the candidates based on the result.
|
// the candidates based on the result.
|
||||||
|
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::expr::as_place::PlaceBuilder;
|
||||||
use crate::build::matches::{Candidate, MatchPair, Test, TestKind};
|
use crate::build::matches::{Candidate, MatchPair, Test, TestCase, TestKind};
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir::{LangItem, RangeEnd};
|
use rustc_hir::{LangItem, RangeEnd};
|
||||||
|
@ -29,58 +29,45 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// It is a bug to call this with a not-fully-simplified pattern.
|
/// It is a bug to call this with a not-fully-simplified pattern.
|
||||||
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
|
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
|
||||||
match match_pair.pattern.kind {
|
let kind = match match_pair.test_case {
|
||||||
PatKind::Variant { adt_def, args: _, variant_index: _, subpatterns: _ } => Test {
|
TestCase::Variant { adt_def, variant_index: _ } => {
|
||||||
span: match_pair.pattern.span,
|
TestKind::Switch { adt_def, variants: BitSet::new_empty(adt_def.variants().len()) }
|
||||||
kind: TestKind::Switch {
|
}
|
||||||
adt_def,
|
|
||||||
variants: BitSet::new_empty(adt_def.variants().len()),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
PatKind::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => {
|
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => {
|
||||||
// For integers, we use a `SwitchInt` match, which allows
|
// For integers, we use a `SwitchInt` match, which allows
|
||||||
// us to handle more cases.
|
// us to handle more cases.
|
||||||
Test {
|
TestKind::SwitchInt {
|
||||||
span: match_pair.pattern.span,
|
switch_ty: match_pair.pattern.ty,
|
||||||
kind: TestKind::SwitchInt {
|
|
||||||
switch_ty: match_pair.pattern.ty,
|
|
||||||
|
|
||||||
// these maps are empty to start; cases are
|
// these maps are empty to start; cases are
|
||||||
// added below in add_cases_to_switch
|
// added below in add_cases_to_switch
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Constant { value } => Test {
|
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
|
||||||
span: match_pair.pattern.span,
|
|
||||||
kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
|
|
||||||
},
|
|
||||||
|
|
||||||
PatKind::Range(ref range) => {
|
TestCase::Range(range) => {
|
||||||
assert_eq!(range.ty, match_pair.pattern.ty);
|
assert_eq!(range.ty, match_pair.pattern.ty);
|
||||||
Test { span: match_pair.pattern.span, kind: TestKind::Range(range.clone()) }
|
TestKind::Range(Box::new(range.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
TestCase::Slice { len, variable_length } => {
|
||||||
let len = prefix.len() + suffix.len();
|
let op = if variable_length { BinOp::Ge } else { BinOp::Eq };
|
||||||
let op = if slice.is_some() { BinOp::Ge } else { BinOp::Eq };
|
TestKind::Len { len: len as u64, op }
|
||||||
Test { span: match_pair.pattern.span, kind: TestKind::Len { len: len as u64, op } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Or { .. } => bug!("or-patterns should have already been handled"),
|
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||||
|
|
||||||
PatKind::AscribeUserType { .. }
|
TestCase::Irrefutable { .. } => span_bug!(
|
||||||
| PatKind::InlineConstant { .. }
|
match_pair.pattern.span,
|
||||||
| PatKind::Array { .. }
|
"simplifiable pattern found: {:?}",
|
||||||
| PatKind::Wild
|
match_pair.pattern
|
||||||
| PatKind::Binding { .. }
|
),
|
||||||
| PatKind::Never
|
};
|
||||||
| PatKind::Leaf { .. }
|
|
||||||
| PatKind::Deref { .. }
|
Test { span: match_pair.pattern.span, kind }
|
||||||
| PatKind::Error(_) => self.error_simplifiable(match_pair),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_cases_to_switch<'pat>(
|
pub(super) fn add_cases_to_switch<'pat>(
|
||||||
|
@ -94,32 +81,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
match match_pair.pattern.kind {
|
match match_pair.test_case {
|
||||||
PatKind::Constant { value } => {
|
TestCase::Constant { value } => {
|
||||||
options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env));
|
options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
PatKind::Variant { .. } => {
|
TestCase::Variant { .. } => {
|
||||||
panic!("you should have called add_variants_to_switch instead!");
|
panic!("you should have called add_variants_to_switch instead!");
|
||||||
}
|
}
|
||||||
PatKind::Range(ref range) => {
|
TestCase::Range(ref range) => {
|
||||||
// Check that none of the switch values are in the range.
|
// Check that none of the switch values are in the range.
|
||||||
self.values_not_contained_in_range(&*range, options).unwrap_or(false)
|
self.values_not_contained_in_range(&*range, options).unwrap_or(false)
|
||||||
}
|
}
|
||||||
PatKind::Slice { .. }
|
// don't know how to add these patterns to a switch
|
||||||
| PatKind::Array { .. }
|
_ => false,
|
||||||
| PatKind::Wild
|
|
||||||
| PatKind::Never
|
|
||||||
| PatKind::Or { .. }
|
|
||||||
| PatKind::Binding { .. }
|
|
||||||
| PatKind::AscribeUserType { .. }
|
|
||||||
| PatKind::InlineConstant { .. }
|
|
||||||
| PatKind::Leaf { .. }
|
|
||||||
| PatKind::Deref { .. }
|
|
||||||
| PatKind::Error(_) => {
|
|
||||||
// don't know how to add these patterns to a switch
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,17 +109,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
match match_pair.pattern.kind {
|
match match_pair.test_case {
|
||||||
PatKind::Variant { adt_def: _, variant_index, .. } => {
|
TestCase::Variant { variant_index, .. } => {
|
||||||
// We have a pattern testing for variant `variant_index`
|
// We have a pattern testing for variant `variant_index`
|
||||||
// set the corresponding index to true
|
// set the corresponding index to true
|
||||||
variants.insert(variant_index);
|
variants.insert(variant_index);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
// don't know how to add these patterns to a switch
|
||||||
// don't know how to add these patterns to a switch
|
_ => false,
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,12 +564,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
|
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
|
||||||
|
|
||||||
let fully_matched;
|
let fully_matched;
|
||||||
let ret = match (&test.kind, &match_pair.pattern.kind) {
|
let ret = match (&test.kind, &match_pair.test_case) {
|
||||||
// If we are performing a variant switch, then this
|
// If we are performing a variant switch, then this
|
||||||
// informs variant patterns, but nothing else.
|
// informs variant patterns, but nothing else.
|
||||||
(
|
(
|
||||||
&TestKind::Switch { adt_def: tested_adt_def, .. },
|
&TestKind::Switch { adt_def: tested_adt_def, .. },
|
||||||
&PatKind::Variant { adt_def, variant_index, .. },
|
&TestCase::Variant { adt_def, variant_index },
|
||||||
) => {
|
) => {
|
||||||
assert_eq!(adt_def, tested_adt_def);
|
assert_eq!(adt_def, tested_adt_def);
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
|
@ -612,14 +585,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
//
|
//
|
||||||
// FIXME(#29623) we could use PatKind::Range to rule
|
// FIXME(#29623) we could use PatKind::Range to rule
|
||||||
// things out here, in some cases.
|
// things out here, in some cases.
|
||||||
(TestKind::SwitchInt { switch_ty: _, options }, PatKind::Constant { value })
|
(TestKind::SwitchInt { switch_ty: _, options }, TestCase::Constant { value })
|
||||||
if is_switch_ty(match_pair.pattern.ty) =>
|
if is_switch_ty(match_pair.pattern.ty) =>
|
||||||
{
|
{
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
let index = options.get_index_of(value).unwrap();
|
let index = options.get_index_of(value).unwrap();
|
||||||
Some(index)
|
Some(index)
|
||||||
}
|
}
|
||||||
(TestKind::SwitchInt { switch_ty: _, options }, PatKind::Range(range)) => {
|
(TestKind::SwitchInt { switch_ty: _, options }, TestCase::Range(range)) => {
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
let not_contained =
|
let not_contained =
|
||||||
self.values_not_contained_in_range(&*range, options).unwrap_or(false);
|
self.values_not_contained_in_range(&*range, options).unwrap_or(false);
|
||||||
|
@ -637,11 +610,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
(
|
(
|
||||||
&TestKind::Len { len: test_len, op: BinOp::Eq },
|
&TestKind::Len { len: test_len, op: BinOp::Eq },
|
||||||
PatKind::Slice { prefix, slice, suffix },
|
&TestCase::Slice { len, variable_length },
|
||||||
) => {
|
) => {
|
||||||
let pat_len = (prefix.len() + suffix.len()) as u64;
|
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||||
match (test_len.cmp(&pat_len), slice) {
|
(Ordering::Equal, false) => {
|
||||||
(Ordering::Equal, &None) => {
|
|
||||||
// on true, min_len = len = $actual_length,
|
// on true, min_len = len = $actual_length,
|
||||||
// on false, len != $actual_length
|
// on false, len != $actual_length
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
|
@ -654,13 +626,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
Some(1)
|
Some(1)
|
||||||
}
|
}
|
||||||
(Ordering::Equal | Ordering::Greater, &Some(_)) => {
|
(Ordering::Equal | Ordering::Greater, true) => {
|
||||||
// This can match both if $actual_len = test_len >= pat_len,
|
// This can match both if $actual_len = test_len >= pat_len,
|
||||||
// and if $actual_len > test_len. We can't advance.
|
// and if $actual_len > test_len. We can't advance.
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
(Ordering::Greater, &None) => {
|
(Ordering::Greater, false) => {
|
||||||
// test_len != pat_len, so if $actual_len = test_len, then
|
// test_len != pat_len, so if $actual_len = test_len, then
|
||||||
// $actual_len != pat_len.
|
// $actual_len != pat_len.
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
|
@ -670,31 +642,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
&TestKind::Len { len: test_len, op: BinOp::Ge },
|
&TestKind::Len { len: test_len, op: BinOp::Ge },
|
||||||
PatKind::Slice { prefix, slice, suffix },
|
&TestCase::Slice { len, variable_length },
|
||||||
) => {
|
) => {
|
||||||
// the test is `$actual_len >= test_len`
|
// the test is `$actual_len >= test_len`
|
||||||
let pat_len = (prefix.len() + suffix.len()) as u64;
|
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||||
match (test_len.cmp(&pat_len), slice) {
|
(Ordering::Equal, true) => {
|
||||||
(Ordering::Equal, &Some(_)) => {
|
|
||||||
// $actual_len >= test_len = pat_len,
|
// $actual_len >= test_len = pat_len,
|
||||||
// so we can match.
|
// so we can match.
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
(Ordering::Less, _) | (Ordering::Equal, &None) => {
|
(Ordering::Less, _) | (Ordering::Equal, false) => {
|
||||||
// test_len <= pat_len. If $actual_len < test_len,
|
// test_len <= pat_len. If $actual_len < test_len,
|
||||||
// then it is also < pat_len, so the test passing is
|
// then it is also < pat_len, so the test passing is
|
||||||
// necessary (but insufficient).
|
// necessary (but insufficient).
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
(Ordering::Greater, &None) => {
|
(Ordering::Greater, false) => {
|
||||||
// test_len > pat_len. If $actual_len >= test_len > pat_len,
|
// test_len > pat_len. If $actual_len >= test_len > pat_len,
|
||||||
// then we know we won't have a match.
|
// then we know we won't have a match.
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
Some(1)
|
Some(1)
|
||||||
}
|
}
|
||||||
(Ordering::Greater, &Some(_)) => {
|
(Ordering::Greater, true) => {
|
||||||
// test_len < pat_len, and is therefore less
|
// test_len < pat_len, and is therefore less
|
||||||
// strict. This can still go both ways.
|
// strict. This can still go both ways.
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
|
@ -703,8 +674,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(TestKind::Range(test), PatKind::Range(pat)) => {
|
(TestKind::Range(test), &TestCase::Range(pat)) => {
|
||||||
if test == pat {
|
if test.as_ref() == pat {
|
||||||
fully_matched = true;
|
fully_matched = true;
|
||||||
Some(0)
|
Some(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -714,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
if !test.overlaps(pat, self.tcx, self.param_env)? { Some(1) } else { None }
|
if !test.overlaps(pat, self.tcx, self.param_env)? { Some(1) } else { None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(TestKind::Range(range), &PatKind::Constant { value }) => {
|
(TestKind::Range(range), &TestCase::Constant { value }) => {
|
||||||
fully_matched = false;
|
fully_matched = false;
|
||||||
if !range.contains(value, self.tcx, self.param_env)? {
|
if !range.contains(value, self.tcx, self.param_env)? {
|
||||||
// `value` is not contained in the testing range,
|
// `value` is not contained in the testing range,
|
||||||
|
@ -737,7 +708,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// However, at this point we can still encounter or-patterns that were extracted
|
// However, at this point we can still encounter or-patterns that were extracted
|
||||||
// from previous calls to `sort_candidate`, so we need to manually address that
|
// from previous calls to `sort_candidate`, so we need to manually address that
|
||||||
// case to avoid panicking in `self.test()`.
|
// case to avoid panicking in `self.test()`.
|
||||||
if let PatKind::Or { .. } = &match_pair.pattern.kind {
|
if let TestCase::Or { .. } = &match_pair.test_case {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,18 +731,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
||||||
candidate.match_pairs.extend(match_pair.subpairs);
|
candidate.match_pairs.extend(match_pair.subpairs);
|
||||||
// Move or-patterns to the end.
|
// Move or-patterns to the end.
|
||||||
candidate
|
candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
||||||
.match_pairs
|
|
||||||
.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_simplifiable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
|
|
||||||
span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn values_not_contained_in_range(
|
fn values_not_contained_in_range(
|
||||||
&self,
|
&self,
|
||||||
range: &PatRange<'tcx>,
|
range: &PatRange<'tcx>,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::build::expr::as_place::PlaceBase;
|
use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::matches::{MatchPair, TestCase};
|
||||||
use crate::build::matches::MatchPair;
|
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::{self, *};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::TypeVisitableExt;
|
use rustc_middle::ty::TypeVisitableExt;
|
||||||
|
|
||||||
|
@ -117,50 +117,144 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
||||||
let mut subpairs = Vec::new();
|
let mut subpairs = Vec::new();
|
||||||
match pattern.kind {
|
let test_case = match pattern.kind {
|
||||||
PatKind::Constant { .. }
|
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
||||||
| PatKind::Range(_)
|
PatKind::Or { .. } => TestCase::Or,
|
||||||
| PatKind::Or { .. }
|
|
||||||
| PatKind::Never
|
|
||||||
| PatKind::Wild
|
|
||||||
| PatKind::Error(_) => {}
|
|
||||||
|
|
||||||
PatKind::AscribeUserType { ref subpattern, .. } => {
|
PatKind::Range(ref range) => {
|
||||||
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
if range.is_full_range(cx.tcx) == Some(true) {
|
||||||
|
default_irrefutable()
|
||||||
|
} else {
|
||||||
|
TestCase::Range(range)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Binding { ref subpattern, .. } => {
|
PatKind::Constant { value } => TestCase::Constant { value },
|
||||||
|
|
||||||
|
PatKind::AscribeUserType {
|
||||||
|
ascription: thir::Ascription { ref annotation, variance },
|
||||||
|
ref subpattern,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// Apply the type ascription to the value at `match_pair.place`
|
||||||
|
let ascription = place.try_to_place(cx).map(|source| super::Ascription {
|
||||||
|
annotation: annotation.clone(),
|
||||||
|
source,
|
||||||
|
variance,
|
||||||
|
});
|
||||||
|
|
||||||
|
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
||||||
|
TestCase::Irrefutable { ascription, binding: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
PatKind::Binding {
|
||||||
|
name: _,
|
||||||
|
mutability: _,
|
||||||
|
mode,
|
||||||
|
var,
|
||||||
|
ty: _,
|
||||||
|
ref subpattern,
|
||||||
|
is_primary: _,
|
||||||
|
} => {
|
||||||
|
let binding = place.try_to_place(cx).map(|source| super::Binding {
|
||||||
|
span: pattern.span,
|
||||||
|
source,
|
||||||
|
var_id: var,
|
||||||
|
binding_mode: mode,
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(subpattern) = subpattern.as_ref() {
|
if let Some(subpattern) = subpattern.as_ref() {
|
||||||
// this is the `x @ P` case; have to keep matching against `P` now
|
// this is the `x @ P` case; have to keep matching against `P` now
|
||||||
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
||||||
}
|
}
|
||||||
|
TestCase::Irrefutable { ascription: None, binding }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::InlineConstant { subpattern: ref pattern, .. } => {
|
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
|
||||||
|
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
||||||
|
let ascription = place.try_to_place(cx).map(|source| {
|
||||||
|
let span = pattern.span;
|
||||||
|
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
|
||||||
|
let args = ty::InlineConstArgs::new(
|
||||||
|
cx.tcx,
|
||||||
|
ty::InlineConstArgsParts {
|
||||||
|
parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
|
||||||
|
ty: cx.infcx.next_ty_var(TypeVariableOrigin {
|
||||||
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
|
span,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.args;
|
||||||
|
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
|
||||||
|
def.to_def_id(),
|
||||||
|
ty::UserArgs { args, user_self_ty: None },
|
||||||
|
));
|
||||||
|
let annotation = ty::CanonicalUserTypeAnnotation {
|
||||||
|
inferred_ty: pattern.ty,
|
||||||
|
span,
|
||||||
|
user_ty: Box::new(user_ty),
|
||||||
|
};
|
||||||
|
super::Ascription { annotation, source, variance: ty::Contravariant }
|
||||||
|
});
|
||||||
|
|
||||||
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
|
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
|
||||||
|
TestCase::Irrefutable { ascription, binding: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Slice { ref prefix, ref slice, ref suffix }
|
PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||||
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
|
||||||
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
|
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
|
||||||
|
default_irrefutable()
|
||||||
|
}
|
||||||
|
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||||
|
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
|
||||||
|
|
||||||
|
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
||||||
|
default_irrefutable()
|
||||||
|
} else {
|
||||||
|
TestCase::Slice {
|
||||||
|
len: prefix.len() + suffix.len(),
|
||||||
|
variable_length: slice.is_some(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
|
PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => {
|
||||||
let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
|
let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
|
||||||
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
|
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
|
||||||
|
|
||||||
|
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
|
||||||
|
i == variant_index || {
|
||||||
|
(cx.tcx.features().exhaustive_patterns
|
||||||
|
|| cx.tcx.features().min_exhaustive_patterns)
|
||||||
|
&& !v
|
||||||
|
.inhabited_predicate(cx.tcx, adt_def)
|
||||||
|
.instantiate(cx.tcx, args)
|
||||||
|
.apply_ignore_module(cx.tcx, cx.param_env)
|
||||||
|
}
|
||||||
|
}) && (adt_def.did().is_local()
|
||||||
|
|| !adt_def.is_variant_list_non_exhaustive());
|
||||||
|
if irrefutable {
|
||||||
|
default_irrefutable()
|
||||||
|
} else {
|
||||||
|
TestCase::Variant { adt_def, variant_index }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Leaf { ref subpatterns } => {
|
PatKind::Leaf { ref subpatterns } => {
|
||||||
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
|
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
|
||||||
|
default_irrefutable()
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Deref { ref subpattern } => {
|
PatKind::Deref { ref subpattern } => {
|
||||||
let place_builder = place.clone().deref();
|
let place_builder = place.clone().deref();
|
||||||
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
|
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
|
||||||
|
default_irrefutable()
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
MatchPair { place, pattern, subpairs }
|
MatchPair { place, test_case, subpairs, pattern }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,8 +461,10 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G>
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'_> {
|
for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_>
|
||||||
|
{
|
||||||
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||||
let mut diag = DiagnosticBuilder::new(
|
let mut diag = DiagnosticBuilder::new(
|
||||||
dcx,
|
dcx,
|
||||||
level,
|
level,
|
||||||
|
|
|
@ -1073,9 +1073,9 @@ pub(crate) struct ExpectedIdentifier {
|
||||||
pub help_cannot_start_number: Option<HelpIdentifierStartsWithNumber>,
|
pub help_cannot_start_number: Option<HelpIdentifierStartsWithNumber>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
let token_descr = TokenDescription::from_token(&self.token);
|
let token_descr = TokenDescription::from_token(&self.token);
|
||||||
|
|
||||||
let mut diag = DiagnosticBuilder::new(
|
let mut diag = DiagnosticBuilder::new(
|
||||||
|
@ -1133,9 +1133,9 @@ pub(crate) struct ExpectedSemi {
|
||||||
pub sugg: ExpectedSemiSugg,
|
pub sugg: ExpectedSemiSugg,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for ExpectedSemi {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
let token_descr = TokenDescription::from_token(&self.token);
|
let token_descr = TokenDescription::from_token(&self.token);
|
||||||
|
|
||||||
let mut diag = DiagnosticBuilder::new(
|
let mut diag = DiagnosticBuilder::new(
|
||||||
|
|
|
@ -145,7 +145,7 @@ impl SerializedDepGraph {
|
||||||
|
|
||||||
/// A packed representation of an edge's start index and byte width.
|
/// A packed representation of an edge's start index and byte width.
|
||||||
///
|
///
|
||||||
/// This is packed by stealing 2 bits from the start index, which means we only accomodate edge
|
/// This is packed by stealing 2 bits from the start index, which means we only accommodate edge
|
||||||
/// data arrays up to a quarter of our address space. Which seems fine.
|
/// data arrays up to a quarter of our address space. Which seems fine.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct EdgeHeader {
|
struct EdgeHeader {
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::num::NonZero;
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
use rustc_ast::util::literal::LitError;
|
use rustc_ast::util::literal::LitError;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
|
codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed,
|
||||||
Level, MultiSpan,
|
IntoDiagnostic, Level, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
@ -17,9 +17,9 @@ pub struct FeatureGateError {
|
||||||
pub explain: DiagnosticMessage,
|
pub explain: DiagnosticMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for FeatureGateError {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FeatureGateError {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
DiagnosticBuilder::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
|
DiagnosticBuilder::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::solve::GoalSource;
|
||||||
use crate::traits::coherence;
|
use crate::traits::coherence;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::Reveal;
|
|
||||||
use rustc_middle::traits::solve::inspect::ProbeKind;
|
use rustc_middle::traits::solve::inspect::ProbeKind;
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{
|
||||||
CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult,
|
CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult,
|
||||||
|
@ -70,20 +69,6 @@ pub(super) trait GoalKind<'tcx>:
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consider a bound originating from the item bounds of an alias. For this we
|
|
||||||
/// require that the well-formed requirements of the self type of the goal
|
|
||||||
/// are "satisfied from the param-env".
|
|
||||||
/// See [`EvalCtxt::validate_alias_bound_self_from_param_env`].
|
|
||||||
fn consider_alias_bound_candidate(
|
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
|
||||||
goal: Goal<'tcx, Self>,
|
|
||||||
assumption: ty::Clause<'tcx>,
|
|
||||||
) -> QueryResult<'tcx> {
|
|
||||||
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
|
|
||||||
ecx.validate_alias_bound_self_from_param_env(goal)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consider a clause specifically for a `dyn Trait` self type. This requires
|
/// Consider a clause specifically for a `dyn Trait` self type. This requires
|
||||||
/// additionally checking all of the supertraits and object bounds to hold,
|
/// additionally checking all of the supertraits and object bounds to hold,
|
||||||
/// since they're not implied by the well-formedness of the object type.
|
/// since they're not implied by the well-formedness of the object type.
|
||||||
|
@ -636,7 +621,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
for assumption in
|
for assumption in
|
||||||
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
|
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
|
||||||
{
|
{
|
||||||
match G::consider_alias_bound_candidate(self, goal, assumption) {
|
match G::consider_implied_clause(self, goal, assumption, []) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
candidates.push(Candidate { source: CandidateSource::AliasBound, result });
|
candidates.push(Candidate { source: CandidateSource::AliasBound, result });
|
||||||
}
|
}
|
||||||
|
@ -657,105 +642,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that we are allowed to use an alias bound originating from the self
|
|
||||||
/// type of this goal. This means something different depending on the self type's
|
|
||||||
/// alias kind.
|
|
||||||
///
|
|
||||||
/// * Projection: Given a goal with a self type such as `<Ty as Trait>::Assoc`,
|
|
||||||
/// we require that the bound `Ty: Trait` can be proven using either a nested alias
|
|
||||||
/// bound candidate, or a param-env candidate.
|
|
||||||
///
|
|
||||||
/// * Opaque: The param-env must be in `Reveal::UserFacing` mode. Otherwise,
|
|
||||||
/// the goal should be proven by using the hidden type instead.
|
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
|
||||||
pub(super) fn validate_alias_bound_self_from_param_env<G: GoalKind<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
goal: Goal<'tcx, G>,
|
|
||||||
) -> QueryResult<'tcx> {
|
|
||||||
match *goal.predicate.self_ty().kind() {
|
|
||||||
ty::Alias(ty::Projection, projection_ty) => {
|
|
||||||
let mut param_env_candidates = vec![];
|
|
||||||
let self_trait_ref = projection_ty.trait_ref(self.tcx());
|
|
||||||
|
|
||||||
if self_trait_ref.self_ty().is_ty_var() {
|
|
||||||
return self
|
|
||||||
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
let trait_goal: Goal<'_, ty::TraitPredicate<'tcx>> = goal.with(
|
|
||||||
self.tcx(),
|
|
||||||
ty::TraitPredicate {
|
|
||||||
trait_ref: self_trait_ref,
|
|
||||||
polarity: ty::ImplPolarity::Positive,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
self.assemble_param_env_candidates(trait_goal, &mut param_env_candidates);
|
|
||||||
// FIXME: We probably need some sort of recursion depth check here.
|
|
||||||
// Can't come up with an example yet, though, and the worst case
|
|
||||||
// we can have is a compiler stack overflow...
|
|
||||||
self.assemble_alias_bound_candidates(trait_goal, &mut param_env_candidates);
|
|
||||||
|
|
||||||
// FIXME: We must also consider alias-bound candidates for a peculiar
|
|
||||||
// class of built-in candidates that I'll call "defaulted" built-ins.
|
|
||||||
//
|
|
||||||
// For example, we always know that `T: Pointee` is implemented, but
|
|
||||||
// we do not always know what `<T as Pointee>::Metadata` actually is,
|
|
||||||
// similar to if we had a user-defined impl with a `default type ...`.
|
|
||||||
// For these traits, since we're not able to always normalize their
|
|
||||||
// associated types to a concrete type, we must consider their alias bounds
|
|
||||||
// instead, so we can prove bounds such as `<T as Pointee>::Metadata: Copy`.
|
|
||||||
self.assemble_alias_bound_candidates_for_builtin_impl_default_items(
|
|
||||||
trait_goal,
|
|
||||||
&mut param_env_candidates,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.merge_candidates(param_env_candidates)
|
|
||||||
}
|
|
||||||
ty::Alias(ty::Opaque, _opaque_ty) => match goal.param_env.reveal() {
|
|
||||||
Reveal::UserFacing => {
|
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
}
|
|
||||||
Reveal::All => return Err(NoSolution),
|
|
||||||
},
|
|
||||||
_ => bug!("only expected to be called on alias tys"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Assemble a subset of builtin impl candidates for a class of candidates called
|
|
||||||
/// "defaulted" built-in traits.
|
|
||||||
///
|
|
||||||
/// For example, we always know that `T: Pointee` is implemented, but we do not
|
|
||||||
/// always know what `<T as Pointee>::Metadata` actually is! See the comment in
|
|
||||||
/// [`EvalCtxt::validate_alias_bound_self_from_param_env`] for more detail.
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
|
||||||
fn assemble_alias_bound_candidates_for_builtin_impl_default_items<G: GoalKind<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
goal: Goal<'tcx, G>,
|
|
||||||
candidates: &mut Vec<Candidate<'tcx>>,
|
|
||||||
) {
|
|
||||||
let lang_items = self.tcx().lang_items();
|
|
||||||
let trait_def_id = goal.predicate.trait_def_id(self.tcx());
|
|
||||||
|
|
||||||
// You probably shouldn't add anything to this list unless you
|
|
||||||
// know what you're doing.
|
|
||||||
let result = if lang_items.pointee_trait() == Some(trait_def_id) {
|
|
||||||
G::consider_builtin_pointee_candidate(self, goal)
|
|
||||||
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
|
|
||||||
G::consider_builtin_discriminant_kind_candidate(self, goal)
|
|
||||||
} else {
|
|
||||||
Err(NoSolution)
|
|
||||||
};
|
|
||||||
|
|
||||||
match result {
|
|
||||||
Ok(result) => candidates.push(Candidate {
|
|
||||||
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
|
||||||
result,
|
|
||||||
}),
|
|
||||||
Err(NoSolution) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
|
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -98,6 +98,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
|
||||||
query_key: ParamEnvAnd<'tcx, Self>,
|
query_key: ParamEnvAnd<'tcx, Self>,
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
|
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
|
||||||
|
span: Span,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Self::QueryResponse,
|
Self::QueryResponse,
|
||||||
|
@ -118,7 +119,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
|
||||||
|
|
||||||
let InferOk { value, obligations } = infcx
|
let InferOk { value, obligations } = infcx
|
||||||
.instantiate_nll_query_response_and_region_obligations(
|
.instantiate_nll_query_response_and_region_obligations(
|
||||||
&ObligationCause::dummy(),
|
&ObligationCause::dummy_with_span(span),
|
||||||
old_param_env,
|
old_param_env,
|
||||||
&canonical_var_values,
|
&canonical_var_values,
|
||||||
canonical_result,
|
canonical_result,
|
||||||
|
@ -160,7 +161,7 @@ where
|
||||||
|
|
||||||
let mut region_constraints = QueryRegionConstraints::default();
|
let mut region_constraints = QueryRegionConstraints::default();
|
||||||
let (output, error_info, mut obligations, _) =
|
let (output, error_info, mut obligations, _) =
|
||||||
Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
|
Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
|
||||||
infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
|
infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -178,6 +179,7 @@ where
|
||||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||||
infcx,
|
infcx,
|
||||||
&mut region_constraints,
|
&mut region_constraints,
|
||||||
|
span,
|
||||||
) {
|
) {
|
||||||
Ok(((), _, new, certainty)) => {
|
Ok(((), _, new, certainty)) => {
|
||||||
obligations.extend(new);
|
obligations.extend(new);
|
||||||
|
|
|
@ -163,7 +163,7 @@ impl<T: ?Sized> Clone for PtrComponents<T> {
|
||||||
/// It is a pointer to a vtable (virtual call table)
|
/// It is a pointer to a vtable (virtual call table)
|
||||||
/// that represents all the necessary information
|
/// that represents all the necessary information
|
||||||
/// to manipulate the concrete type stored inside a trait object.
|
/// to manipulate the concrete type stored inside a trait object.
|
||||||
/// The vtable notably it contains:
|
/// The vtable notably contains:
|
||||||
///
|
///
|
||||||
/// * type size
|
/// * type size
|
||||||
/// * type alignment
|
/// * type alignment
|
||||||
|
|
|
@ -13,6 +13,8 @@ and [Blackberry QNX][BlackBerry].
|
||||||
|
|
||||||
- Florian Bartels, `Florian.Bartels@elektrobit.com`, https://github.com/flba-eb
|
- Florian Bartels, `Florian.Bartels@elektrobit.com`, https://github.com/flba-eb
|
||||||
- Tristan Roach, `TRoach@blackberry.com`, https://github.com/gh-tr
|
- Tristan Roach, `TRoach@blackberry.com`, https://github.com/gh-tr
|
||||||
|
- Jonathan Pallant `Jonathan.Pallant@ferrous-systems.com`, https://github.com/jonathanpallant
|
||||||
|
- Jorge Aparicio `Jorge.Aparicio@ferrous-systems.com`, https://github.com/japaric
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|
|
@ -4,30 +4,12 @@ error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is
|
||||||
LL | for item in *things { *item = 0 }
|
LL | for item in *things { *item = 0 }
|
||||||
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
||||||
|
|
||||||
error[E0277]: the size for values of type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` cannot be known at compilation time
|
|
||||||
--> $DIR/issue-20605.rs:5:17
|
|
||||||
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
|
||||||
| ^^^^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter`
|
|
||||||
= note: all local variables must have a statically known size
|
|
||||||
= help: unsized locals are gated as an unstable feature
|
|
||||||
|
|
||||||
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||||
--> $DIR/issue-20605.rs:5:17
|
--> $DIR/issue-20605.rs:5:17
|
||||||
|
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
LL | for item in *things { *item = 0 }
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0277]: `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
|
||||||
--> $DIR/issue-20605.rs:5:17
|
|
||||||
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
|
||||||
| ^^^^^^^ `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
|
||||||
|
|
|
||||||
= help: the trait `Iterator` is not implemented for `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter`
|
|
||||||
|
|
||||||
error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||||
--> $DIR/issue-20605.rs:5:17
|
--> $DIR/issue-20605.rs:5:17
|
||||||
|
|
|
|
||||||
|
@ -40,33 +22,13 @@ error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Into
|
||||||
LL | for item in *things { *item = 0 }
|
LL | for item in *things { *item = 0 }
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
|
||||||
--> $DIR/issue-20605.rs:5:5
|
|
||||||
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
|
||||||
note: required by a bound in `None`
|
|
||||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
|
||||||
|
|
||||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
|
||||||
--> $DIR/issue-20605.rs:5:9
|
|
||||||
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
|
||||||
| ^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
|
||||||
= note: all local variables must have a statically known size
|
|
||||||
= help: unsized locals are gated as an unstable feature
|
|
||||||
|
|
||||||
error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
|
|
||||||
--> $DIR/issue-20605.rs:5:27
|
--> $DIR/issue-20605.rs:5:27
|
||||||
|
|
|
|
||||||
LL | for item in *things { *item = 0 }
|
LL | for item in *things { *item = 0 }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0614.
|
Some errors have detailed explanations: E0277, E0614.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -5,14 +5,11 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
|
||||||
for item in *things { *item = 0 }
|
for item in *things { *item = 0 }
|
||||||
//[current]~^ ERROR the size for values of type
|
//[current]~^ ERROR the size for values of type
|
||||||
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
|
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
|
||||||
//[next]~| ERROR the size for values of type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` cannot be known at compilation time
|
|
||||||
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||||
//[next]~| ERROR `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
|
||||||
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||||
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
|
||||||
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
||||||
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
|
||||||
//[next]~| ERROR type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
|
|
||||||
// FIXME(-Znext-solver): these error messages are horrible and have to be
|
// FIXME(-Znext-solver): these error messages are horrible and have to be
|
||||||
// improved before we stabilize the new solver.
|
// improved before we stabilize the new solver.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
error[E0792]: expected generic lifetime parameter, found `'a`
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/issue-90014-tait2.rs:27:9
|
||||||
|
|
|
||||||
|
LL | type Fut<'a> = impl Future<Output = ()>;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | Box::new((async { () },))
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
23
tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs
Normal file
23
tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Regression test for #97099.
|
||||||
|
// This was an ICE because `impl Sized` captures the lifetime 'a.
|
||||||
|
|
||||||
|
trait Trait<E> {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl<'a> Trait<&'a ()> for Foo {
|
||||||
|
type Assoc = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() -> impl for<'a> Trait<&'a ()> {
|
||||||
|
Foo
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
|
||||||
|
foo()
|
||||||
|
//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
13
tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr
Normal file
13
tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/higher-ranked-regions-diag.rs:19:5
|
||||||
|
|
|
||||||
|
LL | fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
|
||||||
|
| -- ---------- opaque type defined here
|
||||||
|
| |
|
||||||
|
| hidden type `<impl for<'a> Trait<&'a ()> as Trait<&'a ()>>::Assoc` captures the lifetime `'a` as defined here
|
||||||
|
LL | foo()
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0700`.
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Basic tests for opaque type inference under for<_> binders.
|
||||||
|
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Trait<'a> {
|
||||||
|
type Ty;
|
||||||
|
}
|
||||||
|
impl<'a, T> Trait<'a> for T {
|
||||||
|
type Ty = &'a ();
|
||||||
|
}
|
||||||
|
|
||||||
|
mod basic_pass {
|
||||||
|
use super::*;
|
||||||
|
type Opq<'a> = impl Sized + 'a;
|
||||||
|
fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
|
||||||
|
//~^ ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
mod capture_rpit {
|
||||||
|
use super::*;
|
||||||
|
fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
|
||||||
|
//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
mod capture_tait {
|
||||||
|
use super::*;
|
||||||
|
type Opq0 = impl Sized;
|
||||||
|
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
|
||||||
|
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
fn test() -> Opq2 {}
|
||||||
|
//~^ ERROR hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
mod capture_tait_complex_pass {
|
||||||
|
use super::*;
|
||||||
|
type Opq0<'a> = impl Sized;
|
||||||
|
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
|
||||||
|
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
fn test() -> Opq2 {}
|
||||||
|
//~^ ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as the above, but make sure that different placeholder regions are not equal.
|
||||||
|
mod capture_tait_complex_fail {
|
||||||
|
use super::*;
|
||||||
|
type Opq0<'a> = impl Sized;
|
||||||
|
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
|
||||||
|
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
fn test() -> Opq2 {}
|
||||||
|
//~^ ERROR hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-defining use because 'static is used.
|
||||||
|
mod constrain_fail0 {
|
||||||
|
use super::*;
|
||||||
|
type Opq0<'a, 'b> = impl Sized;
|
||||||
|
fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
|
||||||
|
//~^ ERROR non-defining opaque type use in defining scope
|
||||||
|
//~| ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-defining use because generic lifetime is used multiple times.
|
||||||
|
mod constrain_fail {
|
||||||
|
use super::*;
|
||||||
|
type Opq0<'a, 'b> = impl Sized;
|
||||||
|
fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
|
||||||
|
//~^ ERROR non-defining opaque type use in defining scope
|
||||||
|
//~| ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
mod constrain_pass {
|
||||||
|
use super::*;
|
||||||
|
type Opq0<'a, 'b> = impl Sized;
|
||||||
|
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
|
||||||
|
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
fn test() -> Opq2 {}
|
||||||
|
//~^ ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,101 @@
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:15:55
|
||||||
|
|
|
||||||
|
LL | type Opq<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:21:58
|
||||||
|
|
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
|
||||||
|
| -- ---------- ^^
|
||||||
|
| | |
|
||||||
|
| | opaque type defined here
|
||||||
|
| hidden type `&'a ()` captures the lifetime `'a` as defined here
|
||||||
|
|
||||||
|
error[E0700]: hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:30:23
|
||||||
|
|
|
||||||
|
LL | type Opq0 = impl Sized;
|
||||||
|
| ---------- opaque type defined here
|
||||||
|
LL | type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
|
||||||
|
| -- hidden type `&'b ()` captures the lifetime `'b` as defined here
|
||||||
|
LL | type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
LL | fn test() -> Opq2 {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:39:23
|
||||||
|
|
|
||||||
|
LL | type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
LL | fn test() -> Opq2 {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error[E0700]: hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:49:23
|
||||||
|
|
|
||||||
|
LL | type Opq0<'a> = impl Sized;
|
||||||
|
| ---------- opaque type defined here
|
||||||
|
LL | type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
|
||||||
|
| -- hidden type `&'b ()` captures the lifetime `'b` as defined here
|
||||||
|
LL | type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
LL | fn test() -> Opq2 {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error[E0792]: non-defining opaque type use in defining scope
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:57:41
|
||||||
|
|
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter
|
||||||
|
|
|
||||||
|
note: for this opaque type
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:56:25
|
||||||
|
|
|
||||||
|
LL | type Opq0<'a, 'b> = impl Sized;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:57:65
|
||||||
|
|
|
||||||
|
LL | type Opq0<'a, 'b> = impl Sized;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: non-defining opaque type use in defining scope
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:66:41
|
||||||
|
|
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
|
||||||
|
|
|
||||||
|
note: for this opaque type
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:65:25
|
||||||
|
|
|
||||||
|
LL | type Opq0<'a, 'b> = impl Sized;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:66:60
|
||||||
|
|
|
||||||
|
LL | type Opq0<'a, 'b> = impl Sized;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-basic.rs:76:23
|
||||||
|
|
|
||||||
|
LL | type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
|
||||||
|
LL | fn test() -> Opq2 {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0700, E0792.
|
||||||
|
For more information about an error, try `rustc --explain E0700`.
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Regression test for #97098.
|
||||||
|
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
type Assoc<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Foo = impl for<'a> Trait<Assoc<'a> = FooAssoc<'a>>;
|
||||||
|
pub type FooAssoc<'a> = impl Sized;
|
||||||
|
|
||||||
|
struct Struct;
|
||||||
|
impl Trait for Struct {
|
||||||
|
type Assoc<'a> = &'a u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FOO: Foo = Struct;
|
||||||
|
//~^ ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/higher-ranked-regions-gat.rs:17:18
|
||||||
|
|
|
||||||
|
LL | pub type FooAssoc<'a> = impl Sized;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | const FOO: Foo = Struct;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0792`.
|
|
@ -14,7 +14,6 @@ pub fn copy_any<T>(t: &T) -> T {
|
||||||
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
|
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
|
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||||
//~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
|
|
||||||
|
|
||||||
// FIXME(-Znext-solver): These error messages are horrible and some of them
|
// FIXME(-Znext-solver): These error messages are horrible and some of them
|
||||||
// are even simple fallout from previous error.
|
// are even simple fallout from previous error.
|
||||||
|
|
|
@ -42,20 +42,7 @@ error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||||
LL | copy::<dyn Setup<From=T>>(t)
|
LL | copy::<dyn Setup<From=T>>(t)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
|
error: aborting due to 4 previous errors
|
||||||
--> $DIR/object-unsafety.rs:12:5
|
|
||||||
|
|
|
||||||
LL | copy::<dyn Setup<From=T>>(t)
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `<dyn Setup<From = T> as Setup>::From`
|
|
||||||
= note: the return type of a function must have a statically known size
|
|
||||||
help: consider further restricting the associated type
|
|
||||||
|
|
|
||||||
LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
|
|
||||||
| +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0308.
|
Some errors have detailed explanations: E0277, E0308.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
39
tests/ui/type-alias-impl-trait/hkl_forbidden.rs
Normal file
39
tests/ui/type-alias-impl-trait/hkl_forbidden.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
fn id(s: &str) -> &str {
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opaque<'a> = impl Sized + 'a;
|
||||||
|
|
||||||
|
fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
|
||||||
|
(id, id) //~ ERROR expected generic lifetime parameter, found `'_`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id2<'a, 'b>(s: (&'a str, &'b str)) -> (&'a str, &'b str) {
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opaque2<'a> = impl Sized + 'a;
|
||||||
|
|
||||||
|
fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'b>) {
|
||||||
|
id2 //~ ERROR expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opaque3<'a> = impl Sized + 'a;
|
||||||
|
|
||||||
|
fn test3(s: &str) -> (impl Fn(&str) -> Opaque3<'_>, Opaque3<'_>) {
|
||||||
|
(id, s) //~ ERROR expected generic lifetime parameter, found `'_`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opaque4<'a> = impl Sized + 'a;
|
||||||
|
fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
|
||||||
|
(s, id) //~ ERROR expected generic lifetime parameter, found `'_`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inner<'a> = impl Sized;
|
||||||
|
fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
|
||||||
|
|x| x //~ ERROR expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
48
tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
Normal file
48
tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||||
|
--> $DIR/hkl_forbidden.rs:10:5
|
||||||
|
|
|
||||||
|
LL | type Opaque<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | (id, id)
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/hkl_forbidden.rs:20:5
|
||||||
|
|
|
||||||
|
LL | type Opaque2<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | id2
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||||
|
--> $DIR/hkl_forbidden.rs:26:5
|
||||||
|
|
|
||||||
|
LL | type Opaque3<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | (id, s)
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||||
|
--> $DIR/hkl_forbidden.rs:31:5
|
||||||
|
|
|
||||||
|
LL | type Opaque4<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
|
||||||
|
LL | (s, id)
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/hkl_forbidden.rs:36:5
|
||||||
|
|
|
||||||
|
LL | type Inner<'a> = impl Sized;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL | fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
|
||||||
|
LL | |x| x
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0792`.
|
18
tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
Normal file
18
tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
type Opaque<'a> = impl Sized + 'a;
|
||||||
|
|
||||||
|
trait Trait<'a> {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Trait<'a> for () {
|
||||||
|
type Assoc = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() -> &'static dyn for<'a> Trait<'a, Assoc = Opaque<'a>> {
|
||||||
|
&()
|
||||||
|
//~^ ERROR: expected generic lifetime parameter, found `'a`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
Normal file
12
tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/hkl_forbidden2.rs:14:5
|
||||||
|
|
|
||||||
|
LL | type Opaque<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
...
|
||||||
|
LL | &()
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0792`.
|
13
tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
Normal file
13
tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
type Opaque<'a> = impl Sized + 'a;
|
||||||
|
|
||||||
|
fn foo<'a>(x: &'a ()) -> &'a () {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() -> for<'a> fn(&'a ()) -> Opaque<'a> {
|
||||||
|
foo //~ ERROR: mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
15
tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
Normal file
15
tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/hkl_forbidden3.rs:10:5
|
||||||
|
|
|
||||||
|
LL | type Opaque<'a> = impl Sized + 'a;
|
||||||
|
| --------------- the expected opaque type
|
||||||
|
...
|
||||||
|
LL | foo
|
||||||
|
| ^^^ one type is more general than the other
|
||||||
|
|
|
||||||
|
= note: expected fn pointer `for<'a> fn(&'a ()) -> Opaque<'a>`
|
||||||
|
found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue