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:
bors 2024-02-22 18:39:34 +00:00
commit d9ae43c787
36 changed files with 688 additions and 483 deletions

View File

@ -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);
}

View File

@ -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 {

View File

@ -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())
}
}

View File

@ -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, _) => {

View File

@ -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();
}
}
}
}

View File

@ -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,
);
}
}
}
}

View File

@ -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

View File

@ -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.

View File

@ -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(())
}
}

View File

@ -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>,

View File

@ -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 }
}
}

View File

@ -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,

View File

@ -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(

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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.
}

View File

@ -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

View 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() {}

View 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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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.

View File

@ -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`.

View 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() {}

View 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`.

View 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() {}

View 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`.

View 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() {}

View 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`.