mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 05:53:10 +00:00
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
@ -153,12 +153,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
|
||||
if prev.ty != ty {
|
||||
let guar = ty.error_reported().err().unwrap_or_else(|| {
|
||||
prev.report_mismatch(
|
||||
&OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
opaque_type_key.def_id,
|
||||
infcx.tcx,
|
||||
)
|
||||
.emit()
|
||||
let (Ok(e) | Err(e)) = prev
|
||||
.build_mismatch_error(
|
||||
&OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
opaque_type_key.def_id,
|
||||
infcx.tcx,
|
||||
)
|
||||
.map(|d| d.emit());
|
||||
e
|
||||
});
|
||||
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>) {
|
||||
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);
|
||||
diag.span(MultiSpan::from_spans(diagnostic.spans));
|
||||
for child in diagnostic.children {
|
||||
|
@ -477,7 +477,7 @@ fn sanity_check_found_hidden_type<'tcx>(
|
||||
} else {
|
||||
let span = tcx.def_span(key.def_id);
|
||||
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 {
|
||||
tcx.adt_def(tcx.local_parent(def_id)).repr()
|
||||
} else {
|
||||
tcx.repr_options_of_def(def_id.to_def_id())
|
||||
tcx.repr_options_of_def(def_id)
|
||||
};
|
||||
let (kind, variants) = match &item.kind {
|
||||
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
|
||||
if !hidden.ty.references_error() {
|
||||
for concrete_type in locator.typeck_types {
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty)
|
||||
&& !(concrete_type, hidden).references_error()
|
||||
{
|
||||
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
d.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
|
||||
if !hidden.ty.references_error() {
|
||||
for concrete_type in locator.typeck_types {
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty)
|
||||
&& !(concrete_type, hidden).references_error()
|
||||
{
|
||||
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,8 +287,10 @@ impl TaitConstraintLocator<'_> {
|
||||
if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
|
||||
debug!(?concrete_type, "found constraint");
|
||||
if let Some(prev) = &mut self.found {
|
||||
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
||||
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
|
||||
if concrete_type.ty != prev.ty {
|
||||
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);
|
||||
}
|
||||
} 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),
|
||||
);
|
||||
if let Some(prev) = &mut hir_opaque_ty {
|
||||
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
||||
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
|
||||
tcx.def_span(opaque_type_key.def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
);
|
||||
if concrete_type.ty != prev.ty {
|
||||
if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
d.stash(
|
||||
tcx.def_span(opaque_type_key.def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hir_opaque_ty = Some(concrete_type);
|
||||
@ -436,9 +440,12 @@ impl RpitConstraintChecker<'_> {
|
||||
|
||||
debug!(?concrete_type, "found constraint");
|
||||
|
||||
if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
|
||||
{
|
||||
self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
|
||||
if concrete_type.ty != self.found.ty {
|
||||
if let Ok(d) =
|
||||
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
|
||||
{
|
||||
assert!(!self.fcx.next_trait_solver());
|
||||
hidden_type
|
||||
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
|
||||
.stash(
|
||||
if let Ok(d) = hidden_type.build_mismatch_error(
|
||||
&last_opaque_ty,
|
||||
opaque_type_key.def_id,
|
||||
self.tcx(),
|
||||
) {
|
||||
d.stash(
|
||||
self.tcx().def_span(opaque_type_key.def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -840,12 +840,12 @@ pub struct OpaqueHiddenType<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueHiddenType<'tcx> {
|
||||
pub fn report_mismatch(
|
||||
pub fn build_mismatch_error(
|
||||
&self,
|
||||
other: &Self,
|
||||
opaque_def_id: LocalDefId,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
|
||||
if let Some(diag) = tcx
|
||||
.sess
|
||||
.dcx()
|
||||
@ -853,18 +853,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
|
||||
{
|
||||
diag.cancel();
|
||||
}
|
||||
(self.ty, other.ty).error_reported()?;
|
||||
// Found different concrete types for the opaque type.
|
||||
let sub_diag = if self.span == other.span {
|
||||
TypeMismatchReason::ConflictType { span: self.span }
|
||||
} else {
|
||||
TypeMismatchReason::PreviousUse { span: self.span }
|
||||
};
|
||||
tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
||||
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
||||
self_ty: self.ty,
|
||||
other_ty: other.ty,
|
||||
other_span: other.span,
|
||||
sub: sub_diag,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
#[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())
|
||||
}
|
||||
|
||||
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 size = 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
|
||||
// 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
|
||||
// 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_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::mir::{self, *};
|
||||
use rustc_middle::thir::{self, *};
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
|
||||
use rustc_span::symbol::Symbol;
|
||||
@ -1052,18 +1052,31 @@ struct Ascription<'tcx> {
|
||||
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)]
|
||||
pub(crate) struct MatchPair<'pat, 'tcx> {
|
||||
// This place...
|
||||
/// This place...
|
||||
place: PlaceBuilder<'tcx>,
|
||||
|
||||
// ... must match this pattern.
|
||||
// Invariant: after creation and simplification in `Candidate::new()`, all match pairs must be
|
||||
// simplified, i.e. require a test.
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
/// ... must pass this test...
|
||||
// Invariant: after creation and simplification in `Candidate::new()`, this must not be
|
||||
// `Irrefutable`.
|
||||
test_case: TestCase<'pat, 'tcx>,
|
||||
|
||||
/// Precomputed sub-match pairs of `pattern`.
|
||||
/// ... and these subpairs must match.
|
||||
subpairs: Vec<Self>,
|
||||
|
||||
/// The pattern this was created from.
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
}
|
||||
|
||||
/// See [`Test`] for more.
|
||||
|
@ -13,11 +13,9 @@
|
||||
//! testing a value against a constant.
|
||||
|
||||
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 rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::thir::{self, *};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::thir::{Pat, PatKind};
|
||||
|
||||
use std::mem;
|
||||
|
||||
@ -62,13 +60,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let mut simplified_match_pairs = Vec::new();
|
||||
// Repeatedly simplify match pairs until we're left with only unsimplifiable ones.
|
||||
loop {
|
||||
for match_pair in mem::take(match_pairs) {
|
||||
if let Err(match_pair) = self.simplify_match_pair(
|
||||
match_pair,
|
||||
candidate_bindings,
|
||||
candidate_ascriptions,
|
||||
match_pairs,
|
||||
) {
|
||||
for mut match_pair in mem::take(match_pairs) {
|
||||
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
|
||||
if let Some(binding) = binding {
|
||||
candidate_bindings.push(binding);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -117,133 +126,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
})
|
||||
.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.
|
||||
|
||||
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 rustc_data_structures::fx::FxIndexMap;
|
||||
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.
|
||||
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
|
||||
match match_pair.pattern.kind {
|
||||
PatKind::Variant { adt_def, args: _, variant_index: _, subpatterns: _ } => Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Switch {
|
||||
adt_def,
|
||||
variants: BitSet::new_empty(adt_def.variants().len()),
|
||||
},
|
||||
},
|
||||
let kind = match match_pair.test_case {
|
||||
TestCase::Variant { adt_def, variant_index: _ } => {
|
||||
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
|
||||
// us to handle more cases.
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::SwitchInt {
|
||||
switch_ty: match_pair.pattern.ty,
|
||||
TestKind::SwitchInt {
|
||||
switch_ty: match_pair.pattern.ty,
|
||||
|
||||
// these maps are empty to start; cases are
|
||||
// added below in add_cases_to_switch
|
||||
options: Default::default(),
|
||||
},
|
||||
// these maps are empty to start; cases are
|
||||
// added below in add_cases_to_switch
|
||||
options: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Constant { value } => Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
|
||||
},
|
||||
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
|
||||
|
||||
PatKind::Range(ref range) => {
|
||||
TestCase::Range(range) => {
|
||||
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 } => {
|
||||
let len = prefix.len() + suffix.len();
|
||||
let op = if slice.is_some() { BinOp::Ge } else { BinOp::Eq };
|
||||
Test { span: match_pair.pattern.span, kind: TestKind::Len { len: len as u64, op } }
|
||||
TestCase::Slice { len, variable_length } => {
|
||||
let op = if variable_length { BinOp::Ge } else { BinOp::Eq };
|
||||
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 { .. }
|
||||
| PatKind::InlineConstant { .. }
|
||||
| PatKind::Array { .. }
|
||||
| PatKind::Wild
|
||||
| PatKind::Binding { .. }
|
||||
| PatKind::Never
|
||||
| PatKind::Leaf { .. }
|
||||
| PatKind::Deref { .. }
|
||||
| PatKind::Error(_) => self.error_simplifiable(match_pair),
|
||||
}
|
||||
TestCase::Irrefutable { .. } => span_bug!(
|
||||
match_pair.pattern.span,
|
||||
"simplifiable pattern found: {:?}",
|
||||
match_pair.pattern
|
||||
),
|
||||
};
|
||||
|
||||
Test { span: match_pair.pattern.span, kind }
|
||||
}
|
||||
|
||||
pub(super) fn add_cases_to_switch<'pat>(
|
||||
@ -94,32 +81,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
return false;
|
||||
};
|
||||
|
||||
match match_pair.pattern.kind {
|
||||
PatKind::Constant { value } => {
|
||||
match match_pair.test_case {
|
||||
TestCase::Constant { value } => {
|
||||
options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env));
|
||||
true
|
||||
}
|
||||
PatKind::Variant { .. } => {
|
||||
TestCase::Variant { .. } => {
|
||||
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.
|
||||
self.values_not_contained_in_range(&*range, options).unwrap_or(false)
|
||||
}
|
||||
PatKind::Slice { .. }
|
||||
| PatKind::Array { .. }
|
||||
| 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
|
||||
}
|
||||
// don't know how to add these patterns to a switch
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,17 +109,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
return false;
|
||||
};
|
||||
|
||||
match match_pair.pattern.kind {
|
||||
PatKind::Variant { adt_def: _, variant_index, .. } => {
|
||||
match match_pair.test_case {
|
||||
TestCase::Variant { variant_index, .. } => {
|
||||
// We have a pattern testing for variant `variant_index`
|
||||
// set the corresponding index to true
|
||||
variants.insert(variant_index);
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
// don't know how to add these patterns to a switch
|
||||
false
|
||||
}
|
||||
// don't know how to add these patterns to a switch
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,12 +564,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
|
||||
|
||||
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
|
||||
// informs variant patterns, but nothing else.
|
||||
(
|
||||
&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);
|
||||
fully_matched = true;
|
||||
@ -612,14 +585,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
//
|
||||
// FIXME(#29623) we could use PatKind::Range to rule
|
||||
// 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) =>
|
||||
{
|
||||
fully_matched = true;
|
||||
let index = options.get_index_of(value).unwrap();
|
||||
Some(index)
|
||||
}
|
||||
(TestKind::SwitchInt { switch_ty: _, options }, PatKind::Range(range)) => {
|
||||
(TestKind::SwitchInt { switch_ty: _, options }, TestCase::Range(range)) => {
|
||||
fully_matched = false;
|
||||
let not_contained =
|
||||
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 },
|
||||
PatKind::Slice { prefix, slice, suffix },
|
||||
&TestCase::Slice { len, variable_length },
|
||||
) => {
|
||||
let pat_len = (prefix.len() + suffix.len()) as u64;
|
||||
match (test_len.cmp(&pat_len), slice) {
|
||||
(Ordering::Equal, &None) => {
|
||||
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||
(Ordering::Equal, false) => {
|
||||
// on true, min_len = len = $actual_length,
|
||||
// on false, len != $actual_length
|
||||
fully_matched = true;
|
||||
@ -654,13 +626,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fully_matched = false;
|
||||
Some(1)
|
||||
}
|
||||
(Ordering::Equal | Ordering::Greater, &Some(_)) => {
|
||||
(Ordering::Equal | Ordering::Greater, true) => {
|
||||
// This can match both if $actual_len = test_len >= pat_len,
|
||||
// and if $actual_len > test_len. We can't advance.
|
||||
fully_matched = false;
|
||||
None
|
||||
}
|
||||
(Ordering::Greater, &None) => {
|
||||
(Ordering::Greater, false) => {
|
||||
// test_len != pat_len, so if $actual_len = test_len, then
|
||||
// $actual_len != pat_len.
|
||||
fully_matched = false;
|
||||
@ -670,31 +642,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
(
|
||||
&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`
|
||||
let pat_len = (prefix.len() + suffix.len()) as u64;
|
||||
match (test_len.cmp(&pat_len), slice) {
|
||||
(Ordering::Equal, &Some(_)) => {
|
||||
match (test_len.cmp(&(len as u64)), variable_length) {
|
||||
(Ordering::Equal, true) => {
|
||||
// $actual_len >= test_len = pat_len,
|
||||
// so we can match.
|
||||
fully_matched = true;
|
||||
Some(0)
|
||||
}
|
||||
(Ordering::Less, _) | (Ordering::Equal, &None) => {
|
||||
(Ordering::Less, _) | (Ordering::Equal, false) => {
|
||||
// test_len <= pat_len. If $actual_len < test_len,
|
||||
// then it is also < pat_len, so the test passing is
|
||||
// necessary (but insufficient).
|
||||
fully_matched = false;
|
||||
Some(0)
|
||||
}
|
||||
(Ordering::Greater, &None) => {
|
||||
(Ordering::Greater, false) => {
|
||||
// test_len > pat_len. If $actual_len >= test_len > pat_len,
|
||||
// then we know we won't have a match.
|
||||
fully_matched = false;
|
||||
Some(1)
|
||||
}
|
||||
(Ordering::Greater, &Some(_)) => {
|
||||
(Ordering::Greater, true) => {
|
||||
// test_len < pat_len, and is therefore less
|
||||
// strict. This can still go both ways.
|
||||
fully_matched = false;
|
||||
@ -703,8 +674,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
(TestKind::Range(test), PatKind::Range(pat)) => {
|
||||
if test == pat {
|
||||
(TestKind::Range(test), &TestCase::Range(pat)) => {
|
||||
if test.as_ref() == pat {
|
||||
fully_matched = true;
|
||||
Some(0)
|
||||
} else {
|
||||
@ -714,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
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;
|
||||
if !range.contains(value, self.tcx, self.param_env)? {
|
||||
// `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
|
||||
// from previous calls to `sort_candidate`, so we need to manually address that
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -760,18 +731,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
||||
candidate.match_pairs.extend(match_pair.subpairs);
|
||||
// Move or-patterns to the end.
|
||||
candidate
|
||||
.match_pairs
|
||||
.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||
candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
||||
}
|
||||
|
||||
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(
|
||||
&self,
|
||||
range: &PatRange<'tcx>,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::build::expr::as_place::PlaceBase;
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::matches::MatchPair;
|
||||
use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
|
||||
use crate::build::matches::{MatchPair, TestCase};
|
||||
use crate::build::Builder;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::thir::{self, *};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
|
||||
@ -117,50 +117,144 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
||||
}
|
||||
|
||||
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
||||
let mut subpairs = Vec::new();
|
||||
match pattern.kind {
|
||||
PatKind::Constant { .. }
|
||||
| PatKind::Range(_)
|
||||
| PatKind::Or { .. }
|
||||
| PatKind::Never
|
||||
| PatKind::Wild
|
||||
| PatKind::Error(_) => {}
|
||||
let test_case = match pattern.kind {
|
||||
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
||||
PatKind::Or { .. } => TestCase::Or,
|
||||
|
||||
PatKind::AscribeUserType { ref subpattern, .. } => {
|
||||
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
||||
PatKind::Range(ref range) => {
|
||||
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() {
|
||||
// this is the `x @ P` case; have to keep matching against `P` now
|
||||
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));
|
||||
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);
|
||||
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)`
|
||||
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 } => {
|
||||
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
|
||||
default_irrefutable()
|
||||
}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
let place_builder = place.clone().deref();
|
||||
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>,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'_> {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G>
|
||||
for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_>
|
||||
{
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
|
@ -1073,9 +1073,9 @@ pub(crate) struct ExpectedIdentifier {
|
||||
pub help_cannot_start_number: Option<HelpIdentifierStartsWithNumber>,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
||||
#[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 mut diag = DiagnosticBuilder::new(
|
||||
@ -1133,9 +1133,9 @@ pub(crate) struct ExpectedSemi {
|
||||
pub sugg: ExpectedSemiSugg,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for ExpectedSemi {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
|
||||
#[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 mut diag = DiagnosticBuilder::new(
|
||||
|
@ -145,7 +145,7 @@ impl SerializedDepGraph {
|
||||
|
||||
/// 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.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct EdgeHeader {
|
||||
|
@ -3,8 +3,8 @@ use std::num::NonZero;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::literal::LitError;
|
||||
use rustc_errors::{
|
||||
codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
|
||||
Level, MultiSpan,
|
||||
codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed,
|
||||
IntoDiagnostic, Level, MultiSpan,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -17,9 +17,9 @@ pub struct FeatureGateError {
|
||||
pub explain: DiagnosticMessage,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for FeatureGateError {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FeatureGateError {
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use crate::solve::GoalSource;
|
||||
use crate::traits::coherence;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::traits::solve::inspect::ProbeKind;
|
||||
use rustc_middle::traits::solve::{
|
||||
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
|
||||
/// additionally checking all of the supertraits and object bounds to hold,
|
||||
/// since they're not implied by the well-formedness of the object type.
|
||||
@ -636,7 +621,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
for assumption in
|
||||
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) => {
|
||||
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)]
|
||||
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
|
@ -98,6 +98,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
|
||||
query_key: ParamEnvAnd<'tcx, Self>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<
|
||||
(
|
||||
Self::QueryResponse,
|
||||
@ -118,7 +119,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
|
||||
|
||||
let InferOk { value, obligations } = infcx
|
||||
.instantiate_nll_query_response_and_region_obligations(
|
||||
&ObligationCause::dummy(),
|
||||
&ObligationCause::dummy_with_span(span),
|
||||
old_param_env,
|
||||
&canonical_var_values,
|
||||
canonical_result,
|
||||
@ -160,7 +161,7 @@ where
|
||||
|
||||
let mut region_constraints = QueryRegionConstraints::default();
|
||||
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:?}"))
|
||||
})?;
|
||||
|
||||
@ -178,6 +179,7 @@ where
|
||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||
infcx,
|
||||
&mut region_constraints,
|
||||
span,
|
||||
) {
|
||||
Ok(((), _, new, certainty)) => {
|
||||
obligations.extend(new);
|
||||
|
@ -163,7 +163,7 @@ impl<T: ?Sized> Clone for PtrComponents<T> {
|
||||
/// It is a pointer to a vtable (virtual call table)
|
||||
/// that represents all the necessary information
|
||||
/// to manipulate the concrete type stored inside a trait object.
|
||||
/// The vtable notably it contains:
|
||||
/// The vtable notably contains:
|
||||
///
|
||||
/// * type size
|
||||
/// * type alignment
|
||||
|
@ -13,6 +13,8 @@ and [Blackberry QNX][BlackBerry].
|
||||
|
||||
- Florian Bartels, `Florian.Bartels@elektrobit.com`, https://github.com/flba-eb
|
||||
- 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
|
||||
|
||||
|
@ -4,30 +4,12 @@ error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^ 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
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
|
|
||||
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
|
||||
--> $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 }
|
||||
| ^^^^^^^
|
||||
|
||||
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: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
|
||||
error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
|
||||
--> $DIR/issue-20605.rs:5:27
|
||||
|
|
||||
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.
|
||||
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 }
|
||||
//[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 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 `<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 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 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>::IntoIter as Iterator>::Item` cannot be dereferenced
|
||||
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
|
||||
|
||||
// FIXME(-Znext-solver): these error messages are horrible and have to be
|
||||
// improved before we stabilize the new solver.
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
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
|
||||
|
||||
|
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 mismatched types
|
||||
//~| 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
|
||||
// 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)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
|
||||
--> $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
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
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…
Reference in New Issue
Block a user