diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index a5a906658b89..4b096a592344 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -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); } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index b80ecbc9c659..62d0deb2d3a6 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -510,7 +510,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { 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 { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b945eed54d04..deabb9c37385 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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()) } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 6a42fdb1079f..642009dfa48a 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -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, _) => { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 79cb384c5bde..f0e998b7a003 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -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(); + } } } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index b83a0f893f5f..ed102a7fac0b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -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, ); + } } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index eea3624898c8..30409e990e13 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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, 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 = 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 diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 88a5eae281b3..f9a8795f5d6e 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -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>, ascription: Option> }, + 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, + + /// The pattern this was created from. + pattern: &'pat Pat<'tcx>, } /// See [`Test`] for more. diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 83922dce327d..53a5056cc3f0 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -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>, - ascriptions: &mut Vec>, - match_pairs: &mut Vec>, - ) -> 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(()) - } } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index ae9ebe7170ba..1c97de58863b 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -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, - - // these maps are empty to start; cases are - // added below in add_cases_to_switch - options: Default::default(), - }, + 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(), } } - 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"), - - PatKind::AscribeUserType { .. } - | PatKind::InlineConstant { .. } - | PatKind::Array { .. } - | PatKind::Wild - | PatKind::Binding { .. } - | PatKind::Never - | PatKind::Leaf { .. } - | PatKind::Deref { .. } - | PatKind::Error(_) => self.error_simplifiable(match_pair), - } + TestCase::Or { .. } => bug!("or-patterns should have already been handled"), + + 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>, diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index e42d764147ca..3f7e7a348ed6 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -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(_) => {} - - PatKind::AscribeUserType { ref subpattern, .. } => { + let test_case = match pattern.kind { + PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(), + PatKind::Or { .. } => TestCase::Or, + + PatKind::Range(ref range) => { + if range.is_full_range(cx.tcx) == Some(true) { + default_irrefutable() + } else { + TestCase::Range(range) + } + } + + 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 { ref subpattern, .. } => { + 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 } } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2a42dae289b1..48b93ce0ac5c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -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, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 2d4447a42c2c..2c76e55a46d6 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1073,9 +1073,9 @@ pub(crate) struct ExpectedIdentifier { pub help_cannot_start_number: Option, } -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( diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index f6f6aa07cb3f..3272a0ed1673 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -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 { diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index de7e04ba00f8..73373e9ba587 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -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) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 00c22e9e2c32..8e66b1d580f9 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -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 `::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>( - &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 `::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 `::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 `::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>( - &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>, - ) { - 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>( &mut self, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 12ee778ee05c..faf218131b8b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -98,6 +98,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + '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> + '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); diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index c7b0fe5694a7..fe19f66a31ac 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -163,7 +163,7 @@ impl Clone for PtrComponents { /// 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 diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 2a741fa3d024..56070c2ec34e 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -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 diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 3d753b9c8b88..a44faa5491d3 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -4,30 +4,12 @@ error[E0277]: the trait bound `dyn Iterator: IntoIterator` is LL | for item in *things { *item = 0 } | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` -error[E0277]: the size for values of type ` 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 ` 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 ` as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } | ^^^^^^^ -error[E0277]: ` as IntoIterator>::IntoIter` is not an iterator - --> $DIR/issue-20605.rs:5:17 - | -LL | for item in *things { *item = 0 } - | ^^^^^^^ ` as IntoIterator>::IntoIter` is not an iterator - | - = help: the trait `Iterator` is not implemented for ` as IntoIterator>::IntoIter` - error: the type `&mut as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:5:17 | @@ -40,33 +22,13 @@ error: the type `Option<< as IntoIterator>::Into LL | for item in *things { *item = 0 } | ^^^^^^^ -error[E0277]: the size for values of type `< 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 `< 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 `< 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 `< 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 `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced +error[E0614]: type ` 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`. diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 77d7039fa15e..4a9f62b6612a 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -5,14 +5,11 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } //[current]~^ ERROR the size for values of type //[next]~^^ ERROR the trait bound `dyn Iterator: IntoIterator` is not satisfied - //[next]~| ERROR the size for values of type ` as IntoIterator>::IntoIter` cannot be known at compilation time //[next]~| ERROR the type ` as IntoIterator>::IntoIter` is not well-formed - //[next]~| ERROR ` as IntoIterator>::IntoIter` is not an iterator //[next]~| ERROR the type `&mut as IntoIterator>::IntoIter` is not well-formed - //[next]~| ERROR the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time //[next]~| ERROR the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed - //[next]~| ERROR the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time - //[next]~| ERROR type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced + //[next]~| ERROR type ` 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. } diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr index ed0b2085c885..58390032d92d 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr @@ -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; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | Box::new((async { () },)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs new file mode 100644 index 000000000000..02ed08bd6567 --- /dev/null +++ b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs @@ -0,0 +1,23 @@ +// Regression test for #97099. +// This was an ICE because `impl Sized` captures the lifetime 'a. + +trait Trait { + 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() {} diff --git a/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr new file mode 100644 index 000000000000..c177c3bbf00b --- /dev/null +++ b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr @@ -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 ` 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`. diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs new file mode 100644 index 000000000000..34b94f2e1c78 --- /dev/null +++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs @@ -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() {} diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr new file mode 100644 index 000000000000..fb1e4cca3f40 --- /dev/null +++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr @@ -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`. diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs new file mode 100644 index 000000000000..db5e5e05e54b --- /dev/null +++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs @@ -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 = 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() {} diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr new file mode 100644 index 000000000000..9b361445f1ec --- /dev/null +++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr @@ -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`. diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs index c9b3b1566a4b..4222607b5bfe 100644 --- a/tests/ui/traits/next-solver/object-unsafety.rs +++ b/tests/ui/traits/next-solver/object-unsafety.rs @@ -14,7 +14,6 @@ pub fn copy_any(t: &T) -> T { //~| ERROR the trait bound `dyn Setup: Setup` is not satisfied //~| ERROR mismatched types //~| ERROR the type ` as Setup>::From` is not well-formed - //~| ERROR the size for values of type ` 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. diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index eedca879b0c8..a9cbb721511c 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -42,20 +42,7 @@ error: the type ` as Setup>::From` is not well-formed LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the size for values of type ` as Setup>::From` cannot be known at compilation time - --> $DIR/object-unsafety.rs:12:5 - | -LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for ` 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 where 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`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs new file mode 100644 index 000000000000..c6d1202ef85f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr new file mode 100644 index 000000000000..d49be73d94e7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs new file mode 100644 index 000000000000..3d583d4413d9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr new file mode 100644 index 000000000000..0a9a9d6bcf4e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs new file mode 100644 index 000000000000..a4148599f77a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr new file mode 100644 index 000000000000..d262177a86bc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr @@ -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`.