diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 972c6715ee345..6a30ff40eedc6 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -209,7 +209,7 @@ fn ensure_all_fields_are_const_destruct<'tcx>( tcx, cause, env, - ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref: ty::TraitRef::new(tcx, destruct_trait, [field_ty]), constness: ty::BoundConstness::Maybe, }), diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 49e9944428f53..1ee647fd61a33 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -776,18 +776,18 @@ pub(super) fn assert_only_contains_clauses_from<'tcx>( `{filter:?}` implied bounds: {clause:?}" ); } - ty::ClauseKind::TypeOutlives(outlives_predicate) => { + ty::ClauseKind::TypeOutlives(outlives_clause) => { assert_eq!( - outlives_predicate.0, ty, - "expected `Self` predicate when computing \ + outlives_clause.0, ty, + "expected `Self` clause when computing \ `{filter:?}` implied bounds: {clause:?}" ); } - ty::ClauseKind::HostEffect(host_effect_predicate) => { + ty::ClauseKind::HostEffect(host_effect_clause) => { assert_eq!( - host_effect_predicate.self_ty(), + host_effect_clause.self_ty(), ty, - "expected `Self` predicate when computing \ + "expected `Self` clause when computing \ `{filter:?}` implied bounds: {clause:?}" ); } @@ -836,13 +836,13 @@ pub(super) fn assert_only_contains_clauses_from<'tcx>( PredicateFilter::ConstIfConst => { for (clause, _) in bounds { match clause.kind().skip_binder() { - ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref: _, constness: ty::BoundConstness::Maybe, }) => {} _ => { bug!( - "unexpected non-`HostEffect` predicate when computing \ + "unexpected non-`HostEffect` clause when computing \ `{filter:?}` implied bounds: {clause:?}" ); } @@ -852,23 +852,23 @@ pub(super) fn assert_only_contains_clauses_from<'tcx>( PredicateFilter::SelfConstIfConst => { for (clause, _) in bounds { match clause.kind().skip_binder() { - ty::ClauseKind::HostEffect(pred) => { + ty::ClauseKind::HostEffect(host_clause) => { assert_eq!( - pred.constness, + host_clause.constness, ty::BoundConstness::Maybe, - "expected `[const]` predicate when computing `{filter:?}` \ + "expected `[const]` clause when computing `{filter:?}` \ implied bounds: {clause:?}", ); assert_eq!( - pred.trait_ref.self_ty(), + host_clause.trait_ref.self_ty(), ty, - "expected `Self` predicate when computing `{filter:?}` \ + "expected `Self` clause when computing `{filter:?}` \ implied bounds: {clause:?}" ); } _ => { bug!( - "unexpected non-`HostEffect` predicate when computing \ + "unexpected non-`HostEffect` clause when computing \ `{filter:?}` implied bounds: {clause:?}" ); } @@ -1151,10 +1151,10 @@ pub(super) fn const_conditions<'tcx>( ty::ConstConditions { parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()), - predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| { + clauses: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| { ( clause.kind().map_bound(|clause| match clause { - ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref, constness: ty::BoundConstness::Maybe, }) => trait_ref, @@ -1206,7 +1206,7 @@ pub(super) fn explicit_implied_const_bounds<'tcx>( &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| { ( clause.kind().map_bound(|clause| match clause { - ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref, constness: ty::BoundConstness::Maybe, }) => trait_ref, diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 6b496e775288c..c733292df7d98 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -181,24 +181,24 @@ fn variance_of_opaque( let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id); - for (pred, _) in tcx + for (clause, _) in tcx .explicit_item_bounds(item_def_id) .iter_instantiated_copied(tcx, id_args) .map(Unnormalized::skip_norm_wip) { - debug!(?pred); + debug!(?clause); // We only ignore opaque type args if the opaque type is the outermost type. // The opaque type may be nested within itself via recursion in e.g. // type Foo<'a> = impl PartialEq>; // which thus mentions `'a` and should thus accept hidden types that borrow 'a // instead of requiring an additional `+ 'a`. - match pred.kind().skip_binder() { + match clause.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: _, args, .. }, polarity: _, }) - | ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + | ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref: ty::TraitRef { def_id: _, args, .. }, constness: _, }) => { @@ -219,7 +219,7 @@ fn variance_of_opaque( region.visit_with(&mut collector); } _ => { - pred.visit_with(&mut collector); + clause.visit_with(&mut collector); } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index c0ec4249087c3..be24a5e7d0b8c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -85,8 +85,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClauseKind::Trait(pred) => { (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) } - ty::ClauseKind::HostEffect(pred) => { - (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) + ty::ClauseKind::HostEffect(clause) => { + (clause.trait_ref.args.to_vec(), Some(clause.self_ty().into())) } ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None), ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 701abc117a083..9becad0db1ca2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1192,6 +1192,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); let pat_ty = self.node_ty(decl.pat.hir_id); + if decl.ty.is_none() + && decl.init.is_none() + && !matches!(decl.pat.kind, hir::PatKind::Binding(.., None) | hir::PatKind::Wild) + { + self.register_wf_obligation( + decl_ty.into(), + decl.pat.span, + ObligationCauseCode::WellFormed(None), + ); + } self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); if let Some(blk) = decl.origin.try_get_else() { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a9d524711a141..3f73b14fb85ee 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -2,7 +2,7 @@ use std::any::Any; use std::mem; use std::sync::Arc; -use rustc_data_structures::unord::ExtendUnord; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::attrs::Deprecation; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; @@ -473,7 +473,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // the former. // This is a rudimentary check that does not catch all cases, // just the easiest. - let mut fallback_map: DefIdMap = Default::default(); + let mut fallback_map: FxHashMap = Default::default(); // Issue 46112: We want the map to prefer the shortest // paths when reporting the path to an item. Therefore we @@ -574,10 +574,16 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // We must extend the fallback map with items from the visible parent map // as the extend call overrides existing entries from the latter map, // which we prefer over fallback entries. - let mut merged_visible_parent_map = fallback_map; - merged_visible_parent_map.extend_unord(visible_parent_map.into_items()); + // FIXME: The Unord* APIs lack an efficient way of merging + // the values of one map for only the missing keys of the other map, + // which is required to merge the fallback map into the visible parent map. + // In the meantime, use an "ordered" map internally for fallback entries. + #[allow(rustc::potential_query_instability)] + for (child, parent) in fallback_map { + visible_parent_map.entry(child).or_insert(parent); + } - merged_visible_parent_map + visible_parent_map }, dependency_formats: |tcx, ()| Arc::new(crate::dependency_format::calculate(tcx)), diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a119424f85af1..b8cd0791a783e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -127,10 +127,10 @@ impl<'tcx> ObligationCause<'tcx> { pub fn derived_host_cause( mut self, - parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, variant: impl FnOnce(DerivedHostCause<'tcx>) -> ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { - self.code = variant(DerivedHostCause { parent_host_pred, parent_code: self.code }).into(); + self.code = variant(DerivedHostCause { parent_host_clause, parent_code: self.code }).into(); self } @@ -600,11 +600,11 @@ pub struct ImplDerivedCause<'tcx> { #[derive(Clone, Debug, PartialEq, Eq, StableHash, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct DerivedHostCause<'tcx> { - /// The trait predicate of the parent obligation that led to the + /// The trait clause of the parent obligation that led to the /// current obligation. Note that only trait obligations lead to - /// derived obligations, so we just store the trait predicate here + /// derived obligations, so we just store the trait clause here /// directly. - pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + pub parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, /// The parent trait had this cause. pub parent_code: ObligationCauseCodeHandle<'tcx>, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 029c20d47e524..bfdb89dc409f6 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -537,7 +537,7 @@ impl<'tcx> GenericClauses<'tcx> { #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, StableHash)] pub struct ConstConditions<'tcx> { pub parent: Option, - pub predicates: &'tcx [(ty::PolyTraitRef<'tcx>, Span)], + pub clauses: &'tcx [(ty::PolyTraitRef<'tcx>, Span)], } impl<'tcx> ConstConditions<'tcx> { @@ -559,7 +559,7 @@ impl<'tcx> ConstConditions<'tcx> { + DoubleEndedIterator + ExactSizeIterator + Clone { - EarlyBinder::bind_iter(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { + EarlyBinder::bind_iter(self.clauses).iter_instantiated_copied(tcx, args).map(|u| { let (trait_ref, span) = u.unzip(); (trait_ref, span.skip_normalization()) }) @@ -571,7 +571,7 @@ impl<'tcx> ConstConditions<'tcx> { + DoubleEndedIterator + ExactSizeIterator + Clone { - EarlyBinder::bind_iter(self.predicates).iter_identity_copied().map(|u| { + EarlyBinder::bind_iter(self.clauses).iter_identity_copied().map(|u| { let (trait_ref, span) = u.unzip(); (trait_ref, span.skip_normalization()) }) @@ -588,9 +588,9 @@ impl<'tcx> ConstConditions<'tcx> { tcx.const_conditions(def_id).instantiate_into(tcx, instantiated, args); } instantiated.extend( - self.predicates + self.clauses .iter() - .map(|&(p, s)| (EarlyBinder::bind(tcx, p).instantiate(tcx, args), s)), + .map(|&(c, s)| (EarlyBinder::bind(tcx, c).instantiate(tcx, args), s)), ); } @@ -612,7 +612,7 @@ impl<'tcx> ConstConditions<'tcx> { tcx.const_conditions(def_id).instantiate_identity_into(tcx, instantiated); } instantiated.extend( - self.predicates + self.clauses .iter() .copied() .map(|(trait_ref, span)| (Unnormalized::new(trait_ref), span)), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5328b29561e07..923c48f2fddfa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,7 +87,7 @@ pub use self::pattern::{Pattern, PatternKind}; pub use self::predicate::{ AliasTerm, AliasTermKind, ArgOutlivesClause, Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt, ExistentialProjection, - ExistentialTraitRef, HostEffectPredicate, NormalizesTo, OutlivesClause, PolyCoercePredicate, + ExistentialTraitRef, HostEffectClause, NormalizesTo, OutlivesClause, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesClause, PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesClause, Predicate, PredicateKind, ProjectionPredicate, diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 99de04cd2dcac..990a424289e9b 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -15,7 +15,7 @@ pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate>; pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef>; pub type ExistentialProjection<'tcx> = ir::ExistentialProjection>; pub type TraitPredicate<'tcx> = ir::TraitPredicate>; -pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate>; +pub type HostEffectClause<'tcx> = ir::HostEffectClause>; pub type ClauseKind<'tcx> = ir::ClauseKind>; pub type PredicateKind<'tcx> = ir::PredicateKind>; pub type NormalizesTo<'tcx> = ir::NormalizesTo>; @@ -582,24 +582,16 @@ impl<'tcx> UpcastFrom, PolyProjectionPredicate<'tcx>> for Clause<'t } } -impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>> +impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectClause<'tcx>>> for Predicate<'tcx> { - fn upcast_from( - from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, - tcx: TyCtxt<'tcx>, - ) -> Self { + fn upcast_from(from: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx) } } -impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>> - for Clause<'tcx> -{ - fn upcast_from( - from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, - tcx: TyCtxt<'tcx>, - ) -> Self { +impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectClause<'tcx>>> for Clause<'tcx> { + fn upcast_from(from: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, tcx: TyCtxt<'tcx>) -> Self { from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 85a18775cb873..7fdfd8479b401 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3223,7 +3223,7 @@ define_print! { self.trait_ref.print_trait_sugared().print(p)?; } - ty::HostEffectPredicate<'tcx> { + ty::HostEffectClause<'tcx> { let constness = match self.constness { ty::BoundConstness::Const => { "const" } ty::BoundConstness::Maybe => { "[const]" } @@ -3241,10 +3241,10 @@ define_print! { ty::ClauseKind<'tcx> { match *self { ty::ClauseKind::Trait(ref data) => data.print(p)?, - ty::ClauseKind::RegionOutlives(predicate) => predicate.print(p)?, - ty::ClauseKind::TypeOutlives(predicate) => predicate.print(p)?, + ty::ClauseKind::RegionOutlives(clause) => clause.print(p)?, + ty::ClauseKind::TypeOutlives(clause) => clause.print(p)?, ty::ClauseKind::Projection(predicate) => predicate.print(p)?, - ty::ClauseKind::HostEffect(predicate) => predicate.print(p)?, + ty::ClauseKind::HostEffect(clause) => clause.print(p)?, ty::ClauseKind::ConstArgHasType(ct, ty) => { write!(p, "the constant `")?; ct.print(p)?; diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 58614bf15c7f3..093b930ce9c70 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -165,6 +165,27 @@ where delegate.create_next_universe(); } + compute_query_response_instantiation_values_in_universe( + delegate, + original_values, + response, + span, + prev_universe, + ) +} + +fn compute_query_response_instantiation_values_in_universe( + delegate: &D, + original_values: &[I::GenericArg], + response: &Canonical, + span: I::Span, + prev_universe: ty::UniverseIndex, +) -> CanonicalVarValues +where + D: SolverDelegate, + I: Interner, + T: ResponseT, +{ let var_values = response.value.var_values(); assert_eq!(original_values.len(), var_values.len()); @@ -543,6 +564,7 @@ pub fn instantiate_canonical_state( delegate: &D, span: I::Span, param_env: I::ParamEnv, + prev_universe: ty::UniverseIndex, orig_values: &mut ThinVec, state: inspect::CanonicalState, ) -> T @@ -553,14 +575,23 @@ where { // In case any fresh inference variables have been created between `state` // and the previous instantiation, extend `orig_values` for it. + let max_universe = prev_universe + state.max_universe.index(); + while delegate.universe() < max_universe { + delegate.create_next_universe(); + } orig_values.extend( state.value.var_values.var_values.as_slice()[orig_values.len()..] .iter() - .map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)), + .map(|&arg| delegate.fresh_var_for_kind(arg, span, max_universe)), ); - let instantiation = - compute_query_response_instantiation_values(delegate, orig_values, &state, span); + let instantiation = compute_query_response_instantiation_values_in_universe( + delegate, + orig_values, + &state, + span, + prev_universe, + ); let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation); diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 7b66667486fc9..21a36b3785172 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -26,10 +26,11 @@ pub trait SolverDelegate: Deref + Sized { span: ::Span, ) -> ComputeGoalFastPathOutcome; - fn fresh_var_for_kind_with_span( + fn fresh_var_for_kind( &self, arg: ::GenericArg, span: ::Span, + universe: ty::UniverseIndex, ) -> ::GenericArg; // FIXME: Uplift the leak check into this crate. diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index c6dd456e3e39a..0a361d280033a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -18,7 +18,7 @@ use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, assembly, }; -impl assembly::GoalKind for ty::HostEffectPredicate +impl assembly::GoalKind for ty::HostEffectClause where D: SolverDelegate, I: Interner, @@ -481,7 +481,7 @@ where #[instrument(level = "trace", skip(self))] pub(super) fn compute_host_effect_goal( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResultOrRerunNonErased { let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { let trait_goal: Goal> = diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d836e5f84c6c0..879b239047fdc 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -133,9 +133,9 @@ where ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } - ty::ClauseKind::HostEffect(pred) => { - try_visit!(self.visit_trait(pred.trait_ref)); - pred.constness.visit_with(self) + ty::ClauseKind::HostEffect(clause) => { + try_visit!(self.visit_trait(clause.trait_ref)); + clause.constness.visit_with(self) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_term: projection_ty, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d90c3e81b68ea..9071bf521394d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -636,9 +636,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => self + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(clause)) => self .report_host_effect_error( - bound_predicate.rebind(predicate), + bound_predicate.rebind(clause), &obligation, span, ), @@ -858,22 +858,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn report_host_effect_error( &self, - predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, main_obligation: &PredicateObligation<'tcx>, span: Span, ) -> Diag<'a> { - // FIXME(const_trait_impl): We should recompute the predicate with `[const]` + // FIXME(const_trait_impl): We should recompute the clause with `[const]` // if it's `const`, and if it holds, explain that this bound only // *conditionally* holds. - let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate { - trait_ref: predicate.trait_ref, + let trait_ref = clause.map_bound(|clause| ty::TraitPredicate { + trait_ref: clause.trait_ref, polarity: ty::PredicatePolarity::Positive, }); let mut file = None; let err_msg = self.get_standard_error_message( trait_ref, - Some(predicate.constness()), + Some(clause.constness()), String::new(), &mut file, ); @@ -1512,8 +1512,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn can_match_host_effect( &self, param_env: ty::ParamEnv<'tcx>, - goal: ty::HostEffectPredicate<'tcx>, - assumption: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + goal: ty::HostEffectClause<'tcx>, + assumption: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, ) -> bool { let assumption = self.instantiate_binder_with_fresh_vars( DUMMY_SP, @@ -1527,9 +1527,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn as_host_effect_clause( predicate: ty::Predicate<'tcx>, - ) -> Option>> { + ) -> Option>> { predicate.as_clause().and_then(|clause| match clause.kind().skip_binder() { - ty::ClauseKind::HostEffect(pred) => Some(clause.kind().rebind(pred)), + ty::ClauseKind::HostEffect(host_clause) => Some(clause.kind().rebind(host_clause)), _ => None, }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 094b64b734077..35bedea6c565e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4450,19 +4450,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::ImplDerivedHost(ref data) => { let self_ty = tcx.short_string( - self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty()), + self.resolve_vars_if_possible(data.derived.parent_host_clause.self_ty()), err.long_ty_path(), ); let trait_path = tcx.short_string( data.derived - .parent_host_pred - .map_bound(|pred| pred.trait_ref) + .parent_host_clause + .map_bound(|clause| clause.trait_ref) .print_only_trait_path(), err.long_ty_path(), ); let msg = format!( "required for `{self_ty}` to implement `{} {trait_path}`", - data.derived.parent_host_pred.skip_binder().constness, + data.derived.parent_host_clause.skip_binder().constness, ); match tcx.hir_get_if_local(data.impl_def_id) { Some(Node::Item(hir::Item { @@ -4483,7 +4483,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_obligation_cause_code( body_def_id, err, - data.derived.parent_host_pred, + data.derived.parent_host_clause, param_env, &data.derived.parent_code, obligated_types, @@ -4494,7 +4494,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_obligation_cause_code( body_def_id, err, - data.parent_host_pred, + data.parent_host_clause, param_env, &data.parent_code, obligated_types, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index edfc988dca71f..4f8bac36abb6f 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -285,17 +285,18 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< } } - fn fresh_var_for_kind_with_span( + fn fresh_var_for_kind( &self, arg: ty::GenericArg<'tcx>, span: Span, + universe: ty::UniverseIndex, ) -> ty::GenericArg<'tcx> { match arg.kind() { ty::GenericArgKind::Lifetime(_) => { - self.next_region_var(RegionVariableOrigin::Misc(span)).into() + self.next_region_var_in_universe(RegionVariableOrigin::Misc(span), universe).into() } - ty::GenericArgKind::Type(_) => self.next_ty_var(span).into(), - ty::GenericArgKind::Const(_) => self.next_const_var(span).into(), + ty::GenericArgKind::Type(_) => self.next_ty_var_in_universe(span, universe).into(), + ty::GenericArgKind::Const(_) => self.next_const_var_in_universe(span, universe).into(), } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index a25848b30e2fc..bb75ae6247e38 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -453,8 +453,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { ChildMode::Trait(pred.kind().rebind(trait_pred)) } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => { - ChildMode::Host(pred.kind().rebind(host_pred)) + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_clause)) => { + ChildMode::Host(pred.kind().rebind(host_clause)) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) if projection.projection_term.kind.is_trait_projection() => @@ -520,7 +520,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { impl_where_bound_count += 1; } ( - ChildMode::Host(parent_host_pred), + ChildMode::Host(parent_host_clause), GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, ) => { obligation = make_obligation(derive_host_cause( @@ -528,7 +528,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { candidate.kind(), self.obligation.cause.clone(), impl_where_bound_count, - parent_host_pred, + parent_host_clause, )); impl_where_bound_count += 1; } @@ -556,7 +556,7 @@ enum ChildMode<'tcx> { // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, // and skip all `GoalSource::Misc`, which represent useless obligations // such as alias-eq which may not hold. - Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>), + Host(ty::Binder<'tcx, ty::HostEffectClause<'tcx>>), // Skip trying to derive an `ObligationCause` from this obligation, and // report *all* sub-obligations as if they came directly from the parent // obligation. @@ -604,7 +604,7 @@ fn derive_host_cause<'tcx>( candidate_kind: inspect::ProbeKind>, mut cause: ObligationCause<'tcx>, idx: usize, - parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, ) -> ObligationCause<'tcx> { match candidate_kind { inspect::ProbeKind::TraitCandidate { @@ -620,7 +620,7 @@ fn derive_host_cause<'tcx>( ( trait_ref.to_host_effect_clause( tcx, - parent_host_pred.skip_binder().constness, + parent_host_clause.skip_binder().constness, ), span, ) @@ -629,7 +629,7 @@ fn derive_host_cause<'tcx>( .nth(idx) { cause = - cause.derived_host_cause(parent_host_pred, |derived| { + cause.derived_host_cause(parent_host_clause, |derived| { ObligationCauseCode::ImplDerivedHost(Box::new( traits::ImplDerivedHostCause { derived, impl_def_id, span }, )) @@ -640,8 +640,8 @@ fn derive_host_cause<'tcx>( source: CandidateSource::BuiltinImpl(..), result: _, } => { - cause = - cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost); + cause = cause + .derived_host_cause(parent_host_clause, ObligationCauseCode::BuiltinDerivedHost); } _ => {} }; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 3c581d15f0376..f7d6fe2481b2d 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -32,6 +32,7 @@ pub struct InspectGoal<'a, 'tcx> { infcx: &'a SolverDelegate<'tcx>, depth: usize, orig_values: ThinVec>, + prev_universe: ty::UniverseIndex, goal: Goal<'tcx, ty::Predicate<'tcx>>, result: Result, final_revision: &'tcx inspect::Probe>, @@ -102,7 +103,14 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { match **step { inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push(( source, - instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal), + instantiate_canonical_state( + infcx, + span, + param_env, + self.goal.prev_universe, + &mut orig_values, + goal, + ), )), inspect::ProbeStep::RecordImplArgs { .. } => {} inspect::ProbeStep::MakeCanonicalResponse { .. } @@ -110,8 +118,14 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { } } - let () = - instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state); + let () = instantiate_canonical_state( + infcx, + span, + param_env, + self.goal.prev_universe, + &mut orig_values, + self.final_state, + ); instantiated_goals .into_iter() @@ -139,6 +153,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { infcx, span, param_env, + self.goal.prev_universe, &mut orig_values, impl_args, ); @@ -147,6 +162,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { infcx, span, param_env, + self.goal.prev_universe, &mut orig_values, self.final_state, ); @@ -320,6 +336,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { source: GoalSource, ) -> Self { let infcx = <&SolverDelegate<'tcx>>::from(infcx); + let prev_universe = infcx.universe(); let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, final_revision, result } = root; @@ -331,6 +348,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { infcx, depth, orig_values, + prev_universe, goal: eager_resolve_vars(&**infcx, uncanonicalized_goal), result, final_revision, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 904604b5d0ec1..c885406f6dcfb 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -685,8 +685,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { // if possible. predicates.push_back(bound_predicate.rebind(p)); } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(p)) => { - let p = bound_predicate.rebind(p); + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(c)) => { + let p = bound_predicate.rebind(c); if self.is_param_no_infer(p.skip_binder().trait_ref.args) && is_new_pred { self.add_user_clause(computed_clauses, predicate.expect_clause()); } diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index c0a18f9d14fcb..127a46f60b3d9 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -15,7 +15,7 @@ use thin_vec::{ThinVec, thin_vec}; use super::SelectionContext; use super::normalize::normalize_with_depth_to; -pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>; +pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectClause<'tcx>>; pub enum EvaluationFailure { Ambiguous, @@ -82,7 +82,7 @@ pub fn evaluate_host_effect_obligation<'tcx>( fn match_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, - candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, + candidate: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, candidate_is_unnormalized: bool, more_nested: impl FnOnce(&mut SelectionContext<'_, 'tcx>, &mut ThinVec>), ) -> Result>, NoSolution> { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 28efd58ca48fd..41d2d9adfea74 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -174,8 +174,8 @@ pub fn clause_obligations<'tcx>( wf.add_wf_preds_for_trait_pred(t, Elaborate::None); } ty::ClauseKind::HostEffect(..) => { - // Technically the well-formedness of this predicate is implied by - // the corresponding trait predicate it should've been generated beside. + // Technically the well-formedness of this clause is implied by + // the corresponding trait clause it should've been generated beside. } ty::ClauseKind::RegionOutlives(..) => {} ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ty, _reg)) => { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 6b89f842bd9b0..2db0c83098b54 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -389,7 +389,7 @@ impl FlagComputation { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { self.add_args(trait_pred.trait_ref.args.as_slice()); } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectClause { trait_ref, constness: _, })) => { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index d4ced992829c4..859996d67eb64 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -529,7 +529,7 @@ pub trait Clause>: .transpose() } - fn as_host_effect_clause(self) -> Option>> { + fn as_host_effect_clause(self) -> Option>> { self.kind() .map_bound( |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None }, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 56a911bdb4b8b..cfe5ead83cb01 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -30,7 +30,7 @@ pub trait Interner: + IrPrint> + IrPrint> + IrPrint> - + IrPrint> + + IrPrint> + IrPrint> + IrPrint> + IrPrint> diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index ef70c50b3ae04..1b11665e1f574 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::{AliasConst, ClosureKind}; use crate::{ AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - HostEffectPredicate, Interner, NormalizesTo, OutlivesClause, PatternKind, Placeholder, + HostEffectClause, Interner, NormalizesTo, OutlivesClause, PatternKind, Placeholder, ProjectionPredicate, Region, SubtypePredicate, TraitPredicate, TraitRef, }; @@ -46,7 +46,7 @@ define_display_via_print!( NormalizesTo, SubtypePredicate, CoercePredicate, - HostEffectPredicate, + HostEffectClause, AliasTy, AliasTerm, FnSig, diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 2d04d28a41d58..d04db45eb9ce1 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -175,7 +175,7 @@ impl ty::Binder> { pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause { self.map_bound(|trait_ref| { - ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness }) + ty::ClauseKind::HostEffect(HostEffectClause { trait_ref, constness }) }) .upcast(cx) } @@ -654,15 +654,15 @@ where feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) )] -pub struct HostEffectPredicate { +pub struct HostEffectClause { pub trait_ref: ty::TraitRef, #[lift(identity)] pub constness: BoundConstness, } -impl Eq for HostEffectPredicate {} +impl Eq for HostEffectClause {} -impl HostEffectPredicate { +impl HostEffectClause { pub fn self_ty(self) -> I::Ty { self.trait_ref.self_ty() } @@ -676,7 +676,7 @@ impl HostEffectPredicate { } } -impl ty::Binder> { +impl ty::Binder> { pub fn def_id(self) -> I::TraitId { // Ok to skip binder since trait `DefId` does not care about regions. self.skip_binder().def_id() diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 2b245addc93f4..e57f0f1e0cd8d 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -41,11 +41,11 @@ pub enum ClauseKind { /// Constant initializer must evaluate successfully. ConstEvaluatable(I::Const), - /// Enforces the constness of the predicate we're calling. Like a projection + /// Enforces the constness of the clause we're calling. Like a projection /// goal from a where clause, it's always going to be paired with a /// corresponding trait clause; this just enforces the *constness* of that /// implementation. - HostEffect(ty::HostEffectPredicate), + HostEffect(ty::HostEffectClause), /// Support marking impl as unstable. UnstableFeature( diff --git a/compiler/rustc_type_ir/src/serialize.rs b/compiler/rustc_type_ir/src/serialize.rs index 20358efc162be..7996fd9d32aae 100644 --- a/compiler/rustc_type_ir/src/serialize.rs +++ b/compiler/rustc_type_ir/src/serialize.rs @@ -51,7 +51,7 @@ impl_binder_encode_decode! { ty::ExistentialPredicate, ty::TraitRef, ty::ExistentialTraitRef, - ty::HostEffectPredicate, + ty::HostEffectClause, } impl, I: Interner, E: Encoder> Encodable for ty::Binder diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 8ac567f7ef65b..e62f2763069ce 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -9,7 +9,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::inherent::*; use crate::upcast::Upcast; use crate::{ - Binder, BoundConstness, ClauseKind, HostEffectPredicate, Interner, PredicatePolarity, + Binder, BoundConstness, ClauseKind, HostEffectClause, Interner, PredicatePolarity, TraitPredicate, TraitRef, }; @@ -155,7 +155,7 @@ impl Unnormalized>> { let inner = self .value .map_bound(|trait_ref| { - ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness }) + ClauseKind::HostEffect(HostEffectClause { trait_ref, constness }) }) .upcast(cx); Unnormalized::new(inner) diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index e0d88b27672e0..9aa3064da886f 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -12,7 +12,7 @@ use core::ops::{ Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; -use core::str::FromStr; +use core::str::{FromStr, Utf8Error}; use core::{fmt, hash}; use crate::borrow::{Cow, ToOwned}; @@ -61,6 +61,24 @@ impl ByteString { pub(crate) fn as_mut_bytestr(&mut self) -> &mut ByteStr { ByteStr::from_bytes_mut(&mut self.0) } + /// Try to get a `String` representation of the `&ByteString`, if it is + /// valid UTF-8. + /// + /// This method is named `to_string()` because we want `ByteString` to + /// implement `Display`, but the `ToString` trait has a blanket + /// implementation for types that implement `Display`, and the trait version + /// will use the Unicode replacement character rather than returning a + /// `Result` and allowing for the possibility of the content not being UTF-8. + #[unstable(feature = "bstr_to_string", issue = "134915")] + #[rustc_allow_incoherent_impl] + pub fn to_string(&self) -> Result { + // Avoid allocating a copy of the contents for invalid UTF-8 + if let Err(e) = str::from_utf8(&self.0) { + return Err(e); + } + // SAFETY: we just checked that the contents are valid UTF-8 + Ok(unsafe { String::from_utf8_unchecked(self.0.clone()) }) + } } #[unstable(feature = "bstr", issue = "134915")] @@ -92,7 +110,7 @@ impl fmt::Debug for ByteString { } } -#[unstable(feature = "bstr", issue = "134915")] +#[unstable(feature = "bstr_to_string", issue = "134915")] impl fmt::Display for ByteString { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -676,3 +694,24 @@ impl<'a> TryFrom<&'a ByteStr> for String { Ok(core::str::from_utf8(&s.0)?.into()) } } + +impl ByteStr { + /// Try to get a `String` representation of the `&ByteStr`, if it is valid + /// UTF-8. + /// + /// This method is named `to_string()` because we want `ByteStr` to + /// implement `Display`, but the `ToString` trait has a blanket + /// implementation for types that implement `Display`, and the trait version + /// will use the Unicode replacement character rather than returning a + /// `Result` and allowing for the possibility of the content not being UTF-8. + #[unstable(feature = "bstr_to_string", issue = "134915")] + #[rustc_allow_incoherent_impl] + pub fn to_string(&self) -> Result { + // Avoid allocating a copy of the contents for invalid UTF-8 + if let Err(e) = str::from_utf8(&self.0) { + return Err(e); + } + // SAFETY: we just checked that the contents are valid UTF-8 + Ok(unsafe { String::from_utf8_unchecked(self.0.to_vec()) }) + } +} diff --git a/library/alloctests/tests/bstr.rs b/library/alloctests/tests/bstr.rs new file mode 100644 index 0000000000000..64a1b901f1300 --- /dev/null +++ b/library/alloctests/tests/bstr.rs @@ -0,0 +1,84 @@ +use alloc::bstr::ByteString; +use core::assert_matches; + +#[test] +fn test_debug() { + let b1 = ByteString( + b"\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff".to_vec() + ); + assert_eq!( + r#""\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff""#, + format!("{:?}", b1), + ); +} + +#[test] +fn test_display() { + let b1 = ByteString(b"abc".to_vec()); + let b2 = ByteString(b"\xf0\x28\x8c\xbc".to_vec()); + + assert_eq!(&format!("{b1}"), "abc"); + assert_eq!(&format!("{b2}"), "�(��"); + + assert_eq!(&format!("{b1:<7}!"), "abc !"); + assert_eq!(&format!("{b1:>7}!"), " abc!"); + assert_eq!(&format!("{b1:^7}!"), " abc !"); + assert_eq!(&format!("{b1:^6}!"), " abc !"); + assert_eq!(&format!("{b1:-<7}!"), "abc----!"); + assert_eq!(&format!("{b1:->7}!"), "----abc!"); + assert_eq!(&format!("{b1:-^7}!"), "--abc--!"); + assert_eq!(&format!("{b1:-^6}!"), "-abc--!"); + + assert_eq!(&format!("{b2:<7}!"), "�(�� !"); + assert_eq!(&format!("{b2:>7}!"), " �(��!"); + assert_eq!(&format!("{b2:^7}!"), " �(�� !"); + assert_eq!(&format!("{b2:^6}!"), " �(�� !"); + assert_eq!(&format!("{b2:-<7}!"), "�(��---!"); + assert_eq!(&format!("{b2:->7}!"), "---�(��!"); + assert_eq!(&format!("{b2:-^7}!"), "-�(��--!"); + assert_eq!(&format!("{b2:-^6}!"), "-�(��-!"); + + assert_eq!(&format!("{b1:<2}!"), "abc!"); + assert_eq!(&format!("{b1:>2}!"), "abc!"); + assert_eq!(&format!("{b1:^2}!"), "abc!"); + assert_eq!(&format!("{b1:-<2}!"), "abc!"); + assert_eq!(&format!("{b1:->2}!"), "abc!"); + assert_eq!(&format!("{b1:-^2}!"), "abc!"); + + assert_eq!(&format!("{b2:<3}!"), "�(��!"); + assert_eq!(&format!("{b2:>3}!"), "�(��!"); + assert_eq!(&format!("{b2:^3}!"), "�(��!"); + assert_eq!(&format!("{b2:^2}!"), "�(��!"); + assert_eq!(&format!("{b2:-<3}!"), "�(��!"); + assert_eq!(&format!("{b2:->3}!"), "�(��!"); + assert_eq!(&format!("{b2:-^3}!"), "�(��!"); + assert_eq!(&format!("{b2:-^2}!"), "�(��!"); + + assert_eq!(&format!("{b1:.1}!"), &format!("{:.1}!", "abc")); + assert_eq!(&format!("{b1:.2}!"), &format!("{:.2}!", "abc")); + assert_eq!(&format!("{b1:.3}!"), &format!("{:.3}!", "abc")); + assert_eq!(&format!("{b1:-<5.2}!"), &format!("{:-<5.2}!", "abc")); + assert_eq!(&format!("{b1:-^5.2}!"), &format!("{:-^5.2}!", "abc")); + assert_eq!(&format!("{b1:->5.2}!"), &format!("{:->5.2}!", "abc")); + + assert_eq!(&format!("{b2:.1}!"), "�!"); + assert_eq!(&format!("{b2:.2}!"), "�(!"); + assert_eq!(&format!("{b2:.3}!"), "�(�!"); + assert_eq!(&format!("{b2:.4}!"), "�(��!"); + assert_eq!(&format!("{b2:-<6.3}!"), "�(�---!"); + assert_eq!(&format!("{b2:-^6.3}!"), "-�(�--!"); + assert_eq!(&format!("{b2:->6.3}!"), "---�(�!"); +} + +#[test] +fn test_to_string() { + let b1 = ByteString(b"abc".to_vec()); + let b2 = ByteString(b"\xf0\x28\x8c\xbc".to_vec()); + + assert_eq!(Ok("abc".to_string()), b1.to_string()); + assert_matches!(b2.to_string(), Err(core::str::Utf8Error { .. })); + + // Can still directly use the trait + assert_eq!("abc".to_string(), ToString::to_string(&b1)); + assert_eq!("�(��".to_string(), ToString::to_string(&b2)); +} diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index eb9ea287d950f..b2a3e8f8f8e2a 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -8,6 +8,8 @@ #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_pop_if)] #![feature(borrowed_buf_init)] +#![feature(bstr)] +#![feature(bstr_to_string)] #![feature(buf_read_has_data_left)] #![feature(can_vector)] #![feature(casefold)] @@ -71,6 +73,7 @@ mod arc; mod autotraits; mod borrow; mod boxed; +mod bstr; mod btree_set_hash; mod c_str; mod c_str2; diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index 26a7f9c93b8c7..0530ddc292a99 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -38,6 +38,7 @@ use crate::ops::{Deref, DerefMut, DerefPure}; /// The `Display` implementation behaves as if the `ByteStr` were first lossily converted to a /// `str`, with invalid UTF-8 presented as the Unicode replacement character (�). #[unstable(feature = "bstr", issue = "134915")] +#[rustc_has_incoherent_inherent_impls] #[repr(transparent)] #[doc(alias = "BStr")] pub struct ByteStr(pub [u8]); @@ -171,7 +172,7 @@ impl fmt::Debug for ByteStr { } } -#[unstable(feature = "bstr", issue = "134915")] +#[unstable(feature = "bstr_to_string", issue = "134915")] impl fmt::Display for ByteStr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn emit(byte_str: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index f3bc9840f8e45..0b2a74a0426ac 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -847,6 +847,7 @@ tool_check_step!(Miri { enable_features: ["check_only"], }); tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate }); +tool_check_step!(Priroda { path: "src/tools/miri/priroda", mode: Mode::ToolRustcPrivate }); tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate }); tool_check_step!(RustAnalyzer { path: "src/tools/rust-analyzer", diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index d2142bd37de75..fb24efe119773 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -858,6 +858,64 @@ impl CommandLineStep for CargoMiri { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Priroda { + target: TargetSelection, +} + +impl CommandLineStep for Priroda { + type Output = (); + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/miri/priroda") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Priroda { target: run.target }); + } + + /// Runs `cargo test` for priroda, reusing the Miri sysroot and binary. + fn run(self, builder: &Builder<'_>) { + let host = builder.build.host_target; + let target = self.target; + let stage = builder.top_stage; + + // Priroda tests run under Miri, so reuse the Miri binary and sysroot. + let compilers = RustcPrivateCompilers::new(builder, stage, host); + let miri = builder.ensure(tool::Miri::from_compilers(compilers)); + let target_compiler = compilers.target_compiler(); + + let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target); + builder.std(target_compiler, host); + let host_sysroot = builder.sysroot(target_compiler); + + let mut cargo = tool::prepare_tool_cargo( + builder, + miri.build_compiler, + Mode::ToolRustcPrivate, + host, + Kind::Test, + "src/tools/miri/priroda", + SourceType::InTree, + &[], + ); + + cargo.add_rustc_lib_path(builder); + + let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder); + + cargo.env("MIRI_SYSROOT", &miri_sysroot); + cargo.env("MIRI_HOST_SYSROOT", &host_sysroot); + cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); + + { + let _guard = builder.msg_test("priroda", target, target_compiler.stage); + let _time = helpers::timeit(builder); + cargo.run(builder); + } + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CompiletestTest { host: TargetSelection, diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap index ef5dd1e832e2b..5c15debc2edb7 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap @@ -100,6 +100,9 @@ expression: check [Check] check::CargoMiri targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miri/cargo-miri}) +[Check] check::Priroda + targets: [x86_64-unknown-linux-gnu] + - Set({src/tools/miri/priroda}) [Check] check::MiroptTestTools targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miropt-test-tools}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap index ab58341ceb9e4..677e45333169b 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap @@ -100,6 +100,9 @@ expression: check compiletest --include-default-paths [Check] check::CargoMiri targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miri/cargo-miri}) +[Check] check::Priroda + targets: [x86_64-unknown-linux-gnu] + - Set({src/tools/miri/priroda}) [Check] check::MiroptTestTools targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miropt-test-tools}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap index ce0782792351f..28f6053d4c100 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap @@ -100,6 +100,9 @@ expression: fix [Fix] check::CargoMiri targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miri/cargo-miri}) +[Fix] check::Priroda + targets: [x86_64-unknown-linux-gnu] + - Set({src/tools/miri/priroda}) [Fix] check::MiroptTestTools targets: [x86_64-unknown-linux-gnu] - Set({src/tools/miropt-test-tools}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri.snap index 917498665c6e1..2705be3fc8455 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri.snap @@ -8,3 +8,6 @@ expression: test src/tools/miri [Test] test::CargoMiri targets: [aarch64-unknown-linux-gnu] - Set({src/tools/miri/cargo-miri}) +[Test] test::Priroda + targets: [aarch64-unknown-linux-gnu] + - Set({src/tools/miri/priroda}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri_and_cargo_miri.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri_and_cargo_miri.snap index 3698b48610b41..090150a528866 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri_and_cargo_miri.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_src_tools_miri_and_cargo_miri.snap @@ -8,3 +8,6 @@ expression: test src/tools/miri src/tools/miri/cargo-miri [Test] test::CargoMiri targets: [aarch64-unknown-linux-gnu] - Set({src/tools/miri/cargo-miri}) +[Test] test::Priroda + targets: [aarch64-unknown-linux-gnu] + - Set({src/tools/miri/priroda}) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 6aba8da8a0bac..59060b33a9b13 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -876,6 +876,7 @@ impl<'a> Builder<'a> { check::Clippy, check::Miri, check::CargoMiri, + check::Priroda, check::MiroptTestTools, check::Rustfmt, check::RustAnalyzer, @@ -944,6 +945,7 @@ impl<'a> Builder<'a> { test::Rustfmt, test::Miri, test::CargoMiri, + test::Priroda, test::Clippy, test::CompiletestTest, test::StdarchVerify, diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 54feac39b7153..3c0eb8e332030 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1755,6 +1755,7 @@ mod snapshot { [check] rustc 1 -> Clippy 2 [check] rustc 1 -> Miri 2 [check] rustc 1 -> CargoMiri 2 + [check] rustc 1 -> Priroda 2 [check] rustc 1 -> Rustfmt 2 [check] rustc 1 -> RustAnalyzer 2 [check] rustc 1 -> TestFloatParse 2 diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-miri/check-miri.sh b/src/ci/docker/host-x86_64/x86_64-gnu-miri/check-miri.sh index 9d4ec50e5f534..d6fae3ac9d94f 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-miri/check-miri.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-miri/check-miri.sh @@ -26,7 +26,7 @@ case $HOST_TARGET in python3 "$X_PY" test --stage 2 miri cargo-miri --target aarch64-apple-darwin python3 "$X_PY" test --stage 2 miri cargo-miri --target i686-pc-windows-msvc # Only run "pass" tests for the remaining targets, which is a bit faster. We have to use `miri` - # instead of `src/tools/miri` here to avoid also running the cargo-miri tests. + # instead of `src/tools/miri` here to avoid also running the cargo-miri and priroda tests. python3 "$X_PY" test --stage 2 miri --target x86_64-pc-windows-gnu -- tests/pass python3 "$X_PY" test --stage 2 miri --target i686-unknown-linux-gnu -- tests/pass python3 "$X_PY" test --stage 2 miri --target aarch64-unknown-linux-gnu -- tests/pass diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 23bd71d9dc004..06d9ca7f7ae6c 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -745,8 +745,8 @@ auto: - name: x86_64-msvc-ext2 env: SCRIPT: > - python x.py test --stage 2 src/tools/miri --target x86_64-apple-darwin --test-args pass && - python x.py test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass && + python x.py test --stage 2 miri --target x86_64-apple-darwin --test-args pass && + python x.py test --stage 2 miri --target x86_64-pc-windows-gnu --test-args pass && python x.py miri --stage 2 library/core --test-args notest && python x.py miri --stage 2 library/alloc --test-args notest && python x.py miri --stage 2 library/std --test-args notest diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1be40b539c74b..820c8b550548c 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -371,7 +371,7 @@ fn check_terminator<'tcx>( let fn_ty = func.ty(body, cx.tcx); if let ty::FnDef(fn_def_id, fn_substs) = fn_ty.kind() { // FIXME: when analyzing a function with generic parameters, we may not have enough information to - // resolve to an instance. However, we could check if a host effect predicate can guarantee that + // resolve to an instance. However, we could check if a host effect clause can guarantee that // this can be made a `const` call. let fn_def_id = match Instance::try_resolve( cx.tcx, diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 8b7935fb994a2..4c1b791dbacb8 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -156,7 +156,8 @@ jobs: - name: check build run: | cd ../rust # ./x does not seem to like being invoked from elsewhere - ./x check miri + # checks every tool in that folder (including priroda) + ./x check src/tools/miri # This job is intentionally separate from `test` so that Priroda can be # developed as a separate crate inside the Miri repository for now. diff --git a/src/tools/miri/priroda/Cargo.toml b/src/tools/miri/priroda/Cargo.toml index ff299bae2acbf..48a20fecb0ba8 100644 --- a/src/tools/miri/priroda/Cargo.toml +++ b/src/tools/miri/priroda/Cargo.toml @@ -6,6 +6,7 @@ repository = "https://github.com/rust-lang/miri" version = "0.1.0" edition = "2024" +[workspace] [[bin]] name = "priroda" @@ -24,6 +25,14 @@ miri = { path = ".." } [package.metadata.rust-analyzer] rustc_private = true +# Same lint policy as miri/src/lib.rs. +[lints.rust] +rust_2018_idioms = "warn" + +[lints.clippy] +as_conversions = "warn" +manual_let_else = "warn" + [dev-dependencies] ui_test = "0.30.2" regex = "1.5.5" diff --git a/src/tools/miri/priroda/src/debugger.rs b/src/tools/miri/priroda/src/debugger.rs index b2b7c8779709a..e6428b4f15ebf 100644 --- a/src/tools/miri/priroda/src/debugger.rs +++ b/src/tools/miri/priroda/src/debugger.rs @@ -377,14 +377,11 @@ impl<'tcx> PrirodaContext<'tcx> { /// Initialized bytes are shown in hexadecimal, uninitialized bytes as `??`, /// and complete pointer-sized provenance as pointer markers. fn render_mplace_bytes(&self, mplace: &MPlaceTy<'tcx>) -> InterpResult<'tcx, String> { - let size = match self.ecx.size_and_align_of_val(mplace)? { - Some((size, _)) => size, - None => { - // Extern types cannot currently be executed as by-value locals, - // so this path cannot yet be covered by a Priroda UI fixture. - // FIXME: Add coverage once Priroda supports printing dereferenced places. - return interp_ok("".to_string()); - } + let Some((size, _)) = self.ecx.size_and_align_of_val(mplace)? else { + // Extern types cannot currently be executed as by-value locals, + // so this path cannot yet be covered by a Priroda UI fixture. + // FIXME: Add coverage once Priroda supports printing dereferenced places. + return interp_ok("".to_string()); }; let size = size.bytes_usize(); @@ -508,20 +505,22 @@ impl<'tcx> PrirodaContext<'tcx> { // view before fields can be projected. Structs use their sole // variant directly. Keep the display name tied to the same choice. let (variant_idx, down, name) = if def.is_enum() { - let variant_idx = match self.ecx.read_discriminant(&op).discard_err() { - Some(variant_idx) => variant_idx, + let Some(variant_idx) = + self.ecx.read_discriminant(&op).discard_err() + else { // FIXME: expose this as an explicit render error when // Priroda grows structured value states. Falling back to // bytes keeps today's UI usable but hides why the enum // could not be source-shaped. - None => return self.render_op(op), + return self.render_op(op); }; - let down = match self.ecx.project_downcast(&op, variant_idx).discard_err() { - Some(down) => down, + let Some(down) = + self.ecx.project_downcast(&op, variant_idx).discard_err() + else { // FIXME: distinguish invalid/uninitialized discriminants // from projection bugs in the rendered output once locals // can carry structured diagnostics. - None => return self.render_op(op), + return self.render_op(op); }; let variant_def = &def.variants()[variant_idx]; ( @@ -542,12 +541,13 @@ impl<'tcx> PrirodaContext<'tcx> { let field_idx = FieldIdx::from_usize(i); // `project_field` avoids manual offset math and works for both // immediate and memory-backed operands through `Projectable`. - let field_op = match self.ecx.project_field(&down, field_idx).discard_err() { - Some(field_op) => field_op, + let Some(field_op) = + self.ecx.project_field(&down, field_idx).discard_err() + else { // FIXME: preserve the successfully rendered fields and // mark only this field as unavailable once the value model // can represent partial render failures. - None => return self.render_op(op), + return self.render_op(op); }; fields.push(self.render_source_shaped_op_inner(field_op, depth + 1)); } @@ -578,14 +578,14 @@ impl<'tcx> PrirodaContext<'tcx> { for i in 0..args.len() { // Tuples have no field names in source, so preserve their // source field order and render children positionally. - let field_op = - match self.ecx.project_field(&op, FieldIdx::from_usize(i)).discard_err() { - Some(field_op) => field_op, - // FIXME: render tuple fields independently so one - // projection failure does not throw away the whole - // source-shaped tuple. - None => return self.render_op(op), - }; + let Some(field_op) = + self.ecx.project_field(&op, FieldIdx::from_usize(i)).discard_err() + else { + // FIXME: render tuple fields independently so one + // projection failure does not throw away the whole + // source-shaped tuple. + return self.render_op(op); + }; fields.push(self.render_source_shaped_op_inner(field_op, depth + 1)); } @@ -600,11 +600,10 @@ impl<'tcx> PrirodaContext<'tcx> { // `project_array_fields` uses the dynamic length for slices. That // avoids the classic mistake of treating slice layout as a fixed // zero-length array. - let mut iter = match self.ecx.project_array_fields(&op).discard_err() { - Some(iter) => iter, + let Some(mut iter) = self.ecx.project_array_fields(&op).discard_err() else { // FIXME: when slice metadata is invalid, show that as a slice // length problem instead of silently falling back to raw bytes. - None => return self.render_op(op), + return self.render_op(op); }; let mut fields = Vec::new(); diff --git a/src/tools/miri/priroda/src/frontend/dap.rs b/src/tools/miri/priroda/src/frontend/dap.rs index 6e48510cadc5c..feb6876f4871a 100644 --- a/src/tools/miri/priroda/src/frontend/dap.rs +++ b/src/tools/miri/priroda/src/frontend/dap.rs @@ -494,7 +494,7 @@ impl DapSession { let mut breakpoints = Vec::new(); if let Some(ref req_bps) = args.breakpoints { for req_bp in req_bps { - let line = req_bp.line as usize; + let line = usize::try_from(req_bp.line).unwrap(); session.set_breakpoint(path.clone(), line); breakpoints.push(DapBreakpoint { verified: true, diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs index 9b0efdf9fadb8..e973cda4b2858 100644 --- a/src/tools/miri/priroda/src/main.rs +++ b/src/tools/miri/priroda/src/main.rs @@ -1,19 +1,12 @@ #![feature(rustc_private)] -extern crate miri; extern crate rustc_abi; -extern crate rustc_codegen_ssa; -extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_hir; -extern crate rustc_hir_analysis; -extern crate rustc_index; extern crate rustc_interface; -extern crate rustc_log; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; -extern crate rustc_type_ir; mod debugger; mod frontend; diff --git a/tests/crashes/150040.rs b/tests/crashes/150040.rs deleted file mode 100644 index bf5b7bbf9b536..0000000000000 --- a/tests/crashes/150040.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #150040 - -fn main() { - let [(ref a, b), x]; - a = ""; - b = 5; -} diff --git a/tests/ui/associated-consts/assoc-const-panic-in-match-91514.rs b/tests/ui/associated-consts/assoc-const-panic-in-match-91514.rs new file mode 100644 index 0000000000000..4f37260b3523e --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-panic-in-match-91514.rs @@ -0,0 +1,30 @@ +// Regression test for . +// +// An associated const initialized with `panic!()`, referenced from a `match` arm +// with arms on both sides, used to ICE during codegen. It now fails const-eval +// cleanly instead. The failure only surfaces on a full build (not `check`), since +// the const is evaluated during codegen. + +//@ build-fail + +#![allow(path_statements)] + +struct S; + +impl S { + const CONST: u8 = panic!(); //~ ERROR evaluation panicked: explicit panic +} + +fn f(_: Option<()>, _: Option) {} + +fn main() { + match 0 { + 0 => { + f(None, None); + } + 1 => { + S::CONST; + } + _ => {} + }; +} diff --git a/tests/ui/associated-consts/assoc-const-panic-in-match-91514.stderr b/tests/ui/associated-consts/assoc-const-panic-in-match-91514.stderr new file mode 100644 index 0000000000000..38b0901aa14c9 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-panic-in-match-91514.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation panicked: explicit panic + --> $DIR/assoc-const-panic-in-match-91514.rs:15:23 + | +LL | const CONST: u8 = panic!(); + | ^^^^^^^^ evaluation of `S::CONST` failed here + +note: erroneous constant encountered + --> $DIR/assoc-const-panic-in-match-91514.rs:26:13 + | +LL | S::CONST; + | ^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs index 062853635f285..ca1155da66bee 100644 --- a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs +++ b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs @@ -1,4 +1,4 @@ -// Make sure we don't issue *two* error messages for the trait predicate *and* host predicate. +// Make sure we don't issue *two* error messages for the trait clause *and* host clause. #![feature(const_trait_impl)] diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.rs b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.rs new file mode 100644 index 0000000000000..e9f27ecb7338a --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver=globally + +// Regression test for . +// +// This used to ICE with `-Znext-solver=globally`. +// The ICE happened because the `PartialOrd` bound fails causing +// diagnostics to replay the proof tree in order to find the +// best nested-goal. During that replay, it needs to create a +// fresh inference variable for the higher-ranked `T` but it was +// creating it in the wrong universe. + +#![allow(incomplete_features)] +#![feature(non_lifetime_binders)] + +fn auto_trait() +where + for T: PartialEq + PartialOrd, +{} + +fn main() { + auto_trait(); + //~^ ERROR can't compare `T` with `T` +} diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr new file mode 100644 index 0000000000000..19921e3e06eed --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr @@ -0,0 +1,19 @@ +error[E0277]: can't compare `T` with `T` + --> $DIR/foreach-partial-eq-next-solver.rs:21:5 + | +LL | auto_trait(); + | ^^^^^^^^^^^^ no implementation for `T < T` and `T > T` + | + = help: the trait `PartialOrd` is not implemented for `T` +note: required by a bound in `auto_trait` + --> $DIR/foreach-partial-eq-next-solver.rs:17:27 + | +LL | fn auto_trait() + | ---------- required by a bound in this function +LL | where +LL | for T: PartialEq + PartialOrd, + | ^^^^^^^^^^ required by this bound in `auto_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/let-pat-inferred-non-wf.rs b/tests/ui/wf/let-pat-inferred-non-wf.rs new file mode 100644 index 0000000000000..ab032161ebb51 --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.rs @@ -0,0 +1,58 @@ +// Regression test for https://github.com/rust-lang/rust/issues/150040 +// When a `let PAT;` has no explicit type, later assignments can infer a non-well-formed +// pattern type such as `[str; 2]` or `(str, i32)`. We must reject those array and tuple +// patterns instead of accepting the invalid type or causing ICE. + +#![allow(unused)] + +struct S(T); + +fn should_fail_1() { + let ref y @ [ref x, _]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_2() { + let [ref x]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_3() { + let [[ref x], [_, y @ ..]]; //~ ERROR E0277 + x = ""; + y = []; +} + +fn should_fail_4() { + let [(ref a, b), x]; //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_5() { + let (ref a, b); //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_6() { + let [S(ref x)]; //~ ERROR E0277 + x = ""; +} + +fn should_pass_1() { + let ref x; + x = ""; +} + +fn should_pass_2() { + let ref y @ (ref x,); + x = ""; +} + +fn should_pass_3() { + let S(ref x); + x = ""; +} + +fn main() {} diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr new file mode 100644 index 0000000000000..1c524a22b432b --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -0,0 +1,62 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:11:9 + | +LL | let ref y @ [ref x, _]; + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:16:9 + | +LL | let [ref x]; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:21:9 + | +LL | let [[ref x], [_, y @ ..]]; + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:27:9 + | +LL | let [(ref a, b), x]; + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:33:9 + | +LL | let (ref a, b); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:39:9 + | +LL | let [S(ref x)]; + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `S`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `S` + --> $DIR/let-pat-inferred-non-wf.rs:8:8 + | +LL | struct S(T); + | ^ + = note: slice and array elements must have `Sized` type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`.