diff options
118 files changed, 1031 insertions, 475 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 2f2f7d0aaa4..b7ce3afce7b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -510,16 +510,11 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { .as_var() .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); - if cfg!(debug_assertions) { + if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); let ctxt = get_ctxt_fn(); let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); - let prev = var_to_origin.insert(vid, ctxt); - - // This only makes sense if not called in a canonicalization context. If this - // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin` - // or modify how we track nll region vars for that map. - assert!(matches!(prev, None)); + var_to_origin.insert(vid, ctxt); } next_region @@ -539,16 +534,11 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { .as_var() .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); - if cfg!(debug_assertions) { + if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); let ctxt = get_ctxt_fn(); let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); - let prev = var_to_origin.insert(vid, ctxt); - - // This only makes sense if not called in a canonicalization context. If this - // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin` - // or modify how we track nll region vars for that map. - assert!(matches!(prev, None)); + var_to_origin.insert(vid, ctxt); } next_region diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index dbf15a3e05f..03f175daca9 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -256,11 +256,12 @@ fn sccs_info<'cx, 'tcx>( let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::<Vec<_>>(); var_to_origin_sorted.sort_by_key(|vto| vto.0); - let mut debug_str = "region variables to origins:\n".to_string(); + + let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); for (reg_var, origin) in var_to_origin_sorted.into_iter() { - debug_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin)); + reg_vars_to_origins_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin)); } - debug!(debug_str); + debug!("{}", reg_vars_to_origins_str); let num_components = sccs.scc_data().ranges().len(); let mut components = vec![FxIndexSet::default(); num_components]; @@ -275,12 +276,12 @@ fn sccs_info<'cx, 'tcx>( for (scc_idx, reg_vars_origins) in components.iter().enumerate() { let regions_info = reg_vars_origins.clone().into_iter().collect::<Vec<_>>(); components_str.push_str(&format!( - "{:?}: {:?})", + "{:?}: {:?},\n)", ConstraintSccIndex::from_usize(scc_idx), regions_info, )) } - debug!(components_str); + debug!("{}", components_str); // calculate the best representative for each component let components_representatives = components diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index d96372fb99b..305e2c8fe8e 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -132,9 +132,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> let reg_var = reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - let prev = var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info)); - assert!(matches!(prev, None)); + + if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { + let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); + debug!(?reg_var); + var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info)); + } reg } @@ -149,14 +152,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> let reg_var = reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - if cfg!(debug_assertions) { + if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - let prev = var_to_origin.insert(reg_var, RegionCtxt::Existential(None)); - - // It only makes sense to track region vars in non-canonicalization contexts. If this - // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin` - // or modify how we track nll region vars for that map. - assert!(matches!(prev, None)); + var_to_origin.insert(reg_var, RegionCtxt::Existential(None)); } reg diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index ba58a2e68e9..46692fd5e8b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -424,7 +424,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str .filter_map(|s| { let enable_disable = match s.chars().next() { None => return None, - Some(c @ '+' | c @ '-') => c, + Some(c @ ('+' | '-')) => c, Some(_) => { if diagnostics { sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s }); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 8a9aac14fb6..703c845eafa 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1335,7 +1335,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(), }, ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Subtype(_) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index db58f4af8ec..c41e96290df 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1208,7 +1208,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( fn_sig, Applicability::MachineApplicable, ); - } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { + } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) { diag.span_suggestion( ty.span, "replace with an appropriate return type", @@ -1240,12 +1240,10 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -// FIXME(vincenzopalazzo): remove the hir item when the refactoring is stable fn suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, - _hir_id: hir::HirId, def_id: LocalDefId, ) -> Option<String> { let format_as_assoc: fn(_, _, _, _, _) -> _ = diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 91c64eeec1e..7f1e4ccc964 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -528,7 +528,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_)) | ty::PredicateKind::Clause(ty::Clause::Projection(_)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::WellFormed(_) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 9ee6785970c..357deb07b8f 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -56,7 +56,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 29db16849dd..fb7cb86d734 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = ensure_sufficient_stack(|| match &expr.kind { hir::ExprKind::Path( - qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..), + qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)), ) => self.check_expr_path(qpath, expr, args), _ => self.check_expr_kind(expr, expected), }); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8455076de56..3def97bca47 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -666,7 +666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) // N.B., this predicate is created by breaking down a diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 7273b93b676..18a49ef2f01 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -165,8 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, ty: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> { - let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); - self.err_ctxt().extract_callable_info(body_hir_id, self.param_env, ty) + self.err_ctxt().extract_callable_info(self.body_id, self.param_env, ty) } pub fn suggest_two_fn_call( diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b6d39341fe7..0eff5c956ef 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0c8854e962a..d240d8e491f 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -30,6 +30,8 @@ use super::*; use rustc_middle::ty::relate::{Relate, TypeRelation}; use rustc_middle::ty::{Const, ImplSubject}; +use std::cell::Cell; + /// Whether we should define opaque types or just treat them opaquely. /// /// Currently only used to prevent predicate matching from matching anything @@ -82,6 +84,7 @@ impl<'tcx> InferCtxt<'tcx> { in_snapshot: self.in_snapshot.clone(), universe: self.universe.clone(), intercrate: self.intercrate, + inside_canonicalization_ctxt: Cell::new(self.inside_canonicalization_ctxt()), } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 8ac82653c0e..96a5f6532fe 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -561,6 +561,8 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { where V: TypeFoldable<TyCtxt<'tcx>>, { + let _inside_canonical_ctxt_guard = infcx.set_canonicalization_ctxt(); + let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::NEEDS_INFER | TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS` diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 4503af03ca3..88a28e26005 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => { - relation.register_type_equate_obligation(a, b); + relation.register_type_relate_obligation(a, b); Ok(a) } @@ -842,23 +842,25 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() { - ty::PredicateKind::AliasEq(a.into(), b.into()) + ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate) } else { ty::PredicateKind::ConstEquate(a, b) })]); } - /// Register an obligation that both types must be equal to each other. - /// - /// If they aren't equal then the relation doesn't hold. - fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; - - self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq( + /// Register an obligation that both types must be related to each other according to + /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`] + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( a.into(), b.into(), + self.alias_relate_direction(), ))]); } + + /// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction + /// of the relation. + fn alias_relate_direction(&self) -> ty::AliasRelationDirection; } fn int_unification_error<'tcx>( diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index c92a74b6241..38002357cde 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -210,4 +210,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 5c12351226a..6395c4d4b20 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): This isn't right, I think? + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index dbef42db8f1..98cbd4c561c 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations) } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): This isn't right, I think? + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aeb4ddb4212..8f1a1579290 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -39,6 +39,7 @@ use rustc_span::Span; use std::cell::{Cell, RefCell}; use std::fmt; +use std::ops::Drop; use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; @@ -342,6 +343,11 @@ pub struct InferCtxt<'tcx> { /// there is no type that the user could *actually name* that /// would satisfy it. This avoids crippling inference, basically. pub intercrate: bool, + + /// Flag that is set when we enter canonicalization. Used for debugging to ensure + /// that we only collect region information for `BorrowckInferCtxt::reg_var_to_origin` + /// inside non-canonicalization contexts. + inside_canonicalization_ctxt: Cell<bool>, } /// See the `error_reporting` module for more details. @@ -633,6 +639,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { skip_leak_check: Cell::new(false), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, + inside_canonicalization_ctxt: Cell::new(false), } } } @@ -1728,6 +1735,31 @@ impl<'tcx> InferCtxt<'tcx> { } } } + + pub fn inside_canonicalization_ctxt(&self) -> bool { + self.inside_canonicalization_ctxt.get() + } + + pub fn set_canonicalization_ctxt(&self) -> CanonicalizationCtxtGuard<'_, 'tcx> { + let prev_ctxt = self.inside_canonicalization_ctxt(); + self.inside_canonicalization_ctxt.set(true); + CanonicalizationCtxtGuard { prev_ctxt, infcx: self } + } + + fn set_canonicalization_ctxt_to(&self, ctxt: bool) { + self.inside_canonicalization_ctxt.set(ctxt); + } +} + +pub struct CanonicalizationCtxtGuard<'cx, 'tcx> { + prev_ctxt: bool, + infcx: &'cx InferCtxt<'tcx>, +} + +impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> { + fn drop(&mut self) { + self.infcx.set_canonicalization_ctxt_to(self.prev_ctxt) + } } impl<'tcx> TypeErrCtxt<'_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 573cd91a2a2..f5d20cb7ebf 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -28,6 +28,7 @@ use crate::traits::{Obligation, PredicateObligations}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; @@ -55,21 +56,6 @@ where ambient_variance: ty::Variance, ambient_variance_info: ty::VarianceDiagInfo<'tcx>, - - /// When we pass through a set of binders (e.g., when looking into - /// a `fn` type), we push a new bound region scope onto here. This - /// will contain the instantiated region for each region in those - /// binders. When we then encounter a `ReLateBound(d, br)`, we can - /// use the De Bruijn index `d` to find the right scope, and then - /// bound region name `br` to find the specific instantiation from - /// within that scope. See `replace_bound_region`. - /// - /// This field stores the instantiations for late-bound regions in - /// the `a` type. - a_scopes: Vec<BoundRegionScope<'tcx>>, - - /// Same as `a_scopes`, but for the `b` type. - b_scopes: Vec<BoundRegionScope<'tcx>>, } pub trait TypeRelatingDelegate<'tcx> { @@ -147,8 +133,6 @@ where delegate, ambient_variance, ambient_variance_info: ty::VarianceDiagInfo::default(), - a_scopes: vec![], - b_scopes: vec![], } } @@ -166,88 +150,6 @@ where } } - fn create_scope( - &mut self, - value: ty::Binder<'tcx, impl Relate<'tcx>>, - universally_quantified: UniversallyQuantified, - ) -> BoundRegionScope<'tcx> { - let mut scope = BoundRegionScope::default(); - - // Create a callback that creates (via the delegate) either an - // existential or placeholder region as needed. - let mut next_region = { - let delegate = &mut self.delegate; - let mut lazy_universe = None; - move |br: ty::BoundRegion| { - if universally_quantified.0 { - // The first time this closure is called, create a - // new universe for the placeholders we will make - // from here out. - let universe = lazy_universe.unwrap_or_else(|| { - let universe = delegate.create_next_universe(); - lazy_universe = Some(universe); - universe - }); - - let placeholder = ty::PlaceholderRegion { universe, name: br.kind }; - delegate.next_placeholder_region(placeholder) - } else { - delegate.next_existential_region_var(true, br.kind.get_name()) - } - } - }; - - value.skip_binder().visit_with(&mut ScopeInstantiator { - next_region: &mut next_region, - target_index: ty::INNERMOST, - bound_region_scope: &mut scope, - }); - - scope - } - - /// When we encounter binders during the type traversal, we record - /// the value to substitute for each of the things contained in - /// that binder. (This will be either a universal placeholder or - /// an existential inference variable.) Given the De Bruijn index - /// `debruijn` (and name `br`) of some binder we have now - /// encountered, this routine finds the value that we instantiated - /// the region with; to do so, it indexes backwards into the list - /// of ambient scopes `scopes`. - fn lookup_bound_region( - debruijn: ty::DebruijnIndex, - br: &ty::BoundRegion, - first_free_index: ty::DebruijnIndex, - scopes: &[BoundRegionScope<'tcx>], - ) -> ty::Region<'tcx> { - // The debruijn index is a "reverse index" into the - // scopes listing. So when we have INNERMOST (0), we - // want the *last* scope pushed, and so forth. - let debruijn_index = debruijn.index() - first_free_index.index(); - let scope = &scopes[scopes.len() - debruijn_index - 1]; - - // Find this bound region in that scope to map to a - // particular region. - scope.map[br] - } - - /// If `r` is a bound region, find the scope in which it is bound - /// (from `scopes`) and return the value that we instantiated it - /// with. Otherwise just return `r`. - fn replace_bound_region( - &self, - r: ty::Region<'tcx>, - first_free_index: ty::DebruijnIndex, - scopes: &[BoundRegionScope<'tcx>], - ) -> ty::Region<'tcx> { - debug!("replace_bound_regions(scopes={:?})", scopes); - if let ty::ReLateBound(debruijn, br) = *r { - Self::lookup_bound_region(debruijn, &br, first_free_index, scopes) - } else { - r - } - } - /// Push a new outlives requirement into our output set of /// constraints. fn push_outlives( @@ -314,18 +216,9 @@ where self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty); - // The generalized values we extract from `canonical_var_values` have - // been fully instantiated and hence the set of scopes we have - // doesn't matter -- just to be sure, put an empty vector - // in there. - let old_a_scopes = std::mem::take(pair.vid_scopes(self)); - // Relate the generalized kind to the original one. let result = pair.relate_generalized_ty(self, generalized_ty); - // Restore the old scopes now. - *pair.vid_scopes(self) = old_a_scopes; - debug!("relate_ty_var: complete, result = {:?}", result); result } @@ -379,6 +272,97 @@ where trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } + + #[instrument(skip(self), level = "debug")] + fn instantiate_binder_with_placeholders<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T + where + T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy, + { + if let Some(inner) = binder.no_bound_vars() { + return inner; + } + + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut lazy_universe = None; + + move |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = nll_delegate.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, name: br.kind }; + debug!(?placeholder); + let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + } + }; + + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); + debug!(?replaced); + + replaced + } + + #[instrument(skip(self), level = "debug")] + fn instantiate_binder_with_existentials<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T + where + T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy, + { + if let Some(inner) = binder.no_bound_vars() { + return inner; + } + + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut reg_map = FxHashMap::default(); + + move |br: ty::BoundRegion| { + if let Some(ex_reg_var) = reg_map.get(&br) { + return *ex_reg_var; + } else { + let ex_reg_var = + nll_delegate.next_existential_region_var(true, br.kind.get_name()); + debug!(?ex_reg_var); + reg_map.insert(br, ex_reg_var); + + ex_reg_var + } + } + }; + + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); + debug!(?replaced); + + replaced + } } /// When we instantiate an inference variable with a value in @@ -396,14 +380,6 @@ trait VidValuePair<'tcx>: Debug { /// opposite part of the tuple from the vid). fn value_ty(&self) -> Ty<'tcx>; - /// Extract the scopes that apply to whichever side of the tuple - /// the vid was found on. See the comment where this is called - /// for more details on why we want them. - fn vid_scopes<'r, D: TypeRelatingDelegate<'tcx>>( - &self, - relate: &'r mut TypeRelating<'_, 'tcx, D>, - ) -> &'r mut Vec<BoundRegionScope<'tcx>>; - /// Given a generalized type G that should replace the vid, relate /// G to the value, putting G on whichever side the vid would have /// appeared. @@ -425,16 +401,6 @@ impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { self.1 } - fn vid_scopes<'r, D>( - &self, - relate: &'r mut TypeRelating<'_, 'tcx, D>, - ) -> &'r mut Vec<BoundRegionScope<'tcx>> - where - D: TypeRelatingDelegate<'tcx>, - { - &mut relate.a_scopes - } - fn relate_generalized_ty<D>( &self, relate: &mut TypeRelating<'_, 'tcx, D>, @@ -457,16 +423,6 @@ impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { self.0 } - fn vid_scopes<'r, D>( - &self, - relate: &'r mut TypeRelating<'_, 'tcx, D>, - ) -> &'r mut Vec<BoundRegionScope<'tcx>> - where - D: TypeRelatingDelegate<'tcx>, - { - &mut relate.b_scopes - } - fn relate_generalized_ty<D>( &self, relate: &mut TypeRelating<'_, 'tcx, D>, @@ -602,20 +558,14 @@ where ) -> RelateResult<'tcx, ty::Region<'tcx>> { debug!(?self.ambient_variance); - let v_a = self.replace_bound_region(a, ty::INNERMOST, &self.a_scopes); - let v_b = self.replace_bound_region(b, ty::INNERMOST, &self.b_scopes); - - debug!(?v_a); - debug!(?v_b); - if self.ambient_covariance() { // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`. - self.push_outlives(v_a, v_b, self.ambient_variance_info); + self.push_outlives(a, b, self.ambient_variance_info); } if self.ambient_contravariance() { // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`. - self.push_outlives(v_b, v_a, self.ambient_variance_info); + self.push_outlives(b, a, self.ambient_variance_info); } Ok(a) @@ -689,15 +639,6 @@ where // instantiation of B (i.e., B instantiated with // universals). - let b_scope = self.create_scope(b, UniversallyQuantified(true)); - let a_scope = self.create_scope(a, UniversallyQuantified(false)); - - debug!(?a_scope, "(existential)"); - debug!(?b_scope, "(universal)"); - - self.b_scopes.push(b_scope); - self.a_scopes.push(a_scope); - // Reset the ambient variance to covariant. This is needed // to correctly handle cases like // @@ -718,12 +659,14 @@ where // subtyping (i.e., `&'b u32 <: &{P} u32`). let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); - self.relate(a.skip_binder(), b.skip_binder())?; + // Note: the order here is important. Create the placeholders first, otherwise + // we assign the wrong universe to the existential! + let b_replaced = self.instantiate_binder_with_placeholders(b); + let a_replaced = self.instantiate_binder_with_existentials(a); - self.ambient_variance = variance; + self.relate(a_replaced, b_replaced)?; - self.b_scopes.pop().unwrap(); - self.a_scopes.pop().unwrap(); + self.ambient_variance = variance; } if self.ambient_contravariance() { @@ -733,26 +676,17 @@ where // instantiation of B (i.e., B instantiated with // existentials). Opposite of above. - let a_scope = self.create_scope(a, UniversallyQuantified(true)); - let b_scope = self.create_scope(b, UniversallyQuantified(false)); - - debug!(?a_scope, "(universal)"); - debug!(?b_scope, "(existential)"); - - self.a_scopes.push(a_scope); - self.b_scopes.push(b_scope); - // Reset ambient variance to contravariance. See the // covariant case above for an explanation. let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); - self.relate(a.skip_binder(), b.skip_binder())?; + let a_replaced = self.instantiate_binder_with_placeholders(a); + let b_replaced = self.instantiate_binder_with_existentials(b); - self.ambient_variance = variance; + self.relate(a_replaced, b_replaced)?; - self.b_scopes.pop().unwrap(); - self.a_scopes.pop().unwrap(); + self.ambient_variance = variance; } Ok(a) @@ -777,6 +711,34 @@ where fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.delegate.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance") + } + + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Variance::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Variance::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Variance::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + // FIXME(deferred_projection_equality): Implement this when we trigger it. + // Probably just need to do nothing here. + ty::Variance::Bivariant => unreachable!(), + })]); + } } /// When we encounter a binder like `for<..> fn(..)`, we actually have diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 83f3d5a74fb..048dad3a48b 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -22,7 +22,7 @@ pub fn explicit_outlives_bounds<'tcx>( ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::WellFormed(..) diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index f795047709e..fa6529dfa93 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -26,7 +26,7 @@ impl<'tcx> InferCtxt<'tcx> { // completely change the normalization routine with the new solver. // // The new solver correctly handles projection equality so this hack - // is not necessary. if re-enabled it should emit `PredicateKind::AliasEq` + // is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate` // not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver // `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`. return projection_ty.to_ty(self.tcx); diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 230cadb1184..fc73ca7606d 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -236,4 +236,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + ty::AliasRelationDirection::Subtype + } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c07ff516579..0d2faeba5fc 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -293,7 +293,7 @@ impl<'tcx> Elaborator<'tcx> { // Nothing to elaborate } ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasEq(..) => { + ty::PredicateKind::AliasRelate(..) => { // No } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8af1a663ef5..f8dd8299312 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1601,7 +1601,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { // Ignore projections, as they can only be global // if the trait bound is global Clause(Clause::Projection(..)) | - AliasEq(..) | + AliasRelate(..) | // Ignore bounds that a user can't type WellFormed(..) | ObjectSafe(..) | diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 883a56cb3ce..f9d43fe2200 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -27,6 +27,8 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![feature(type_alias_impl_trait)] + /// /// trait Duh {} /// /// impl Duh for i32 {} @@ -41,7 +43,9 @@ declare_lint! { /// type Assoc = F; /// } /// - /// fn test() -> impl Trait<Assoc = impl Sized> { + /// type Tait = impl Sized; + /// + /// fn test() -> impl Trait<Assoc = Tait> { /// 42 /// } /// ``` @@ -54,7 +58,7 @@ declare_lint! { /// /// Although the hidden type, `i32` does satisfy this bound, we do not /// consider the return type to be well-formed with this lint. It can be - /// fixed by changing `impl Sized` into `impl Sized + Send`. + /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`. pub OPAQUE_HIDDEN_INFERRED_BOUND, Warn, "detects the use of nested `impl Trait` types in associated type bounds that are not general enough" @@ -64,7 +68,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; }; + let hir::ItemKind::OpaqueTy(opaque) = &item.kind else { return; }; let def_id = item.owner_id.def_id.to_def_id(); let infcx = &cx.tcx.infer_ctxt().build(); // For every projection predicate in the opaque type's explicit bounds, @@ -81,6 +85,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // have opaques in them anyways. let Some(proj_term) = proj.term.ty() else { continue }; + // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + continue; + } + let proj_ty = cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs); // For every instance of the projection type in the bounds, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0070e46ffdf..54982e7fbab 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -925,10 +925,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { tcx.mk_adt_def(did, adt_kind, variants, repr) } - fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess)) - } - fn get_visibility(self, id: DefIndex) -> Visibility<DefId> { self.root .tables diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9661e815623..7d42883fc9d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -545,10 +545,6 @@ impl CStore { self.get_crate_data(def.krate).def_kind(def.index) } - pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { - self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes - } - pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId { self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess) } @@ -560,14 +556,6 @@ impl CStore { self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs_untracked<'a>( - &'a self, - def_id: DefId, - sess: &'a Session, - ) -> impl Iterator<Item = ast::Attribute> + 'a { - self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess) - } - pub fn get_proc_macro_quoted_span_untracked( &self, cnum: CrateNum, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 91241ff404f..5a6ee123811 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -288,7 +288,7 @@ impl FlagComputation { self.add_ty(ty); } ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasEq(t1, t2) => { + ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); self.add_term(t2); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d383a413208..b17749c1eba 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -543,7 +543,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(Clause::TypeOutlives(_)) | PredicateKind::Clause(Clause::Projection(_)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) @@ -640,7 +640,23 @@ pub enum PredicateKind<'tcx> { /// This predicate requires two terms to be equal to eachother. /// /// Only used for new solver - AliasEq(Term<'tcx>, Term<'tcx>), + AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, Debug)] +pub enum AliasRelationDirection { + Equate, + Subtype, +} + +impl std::fmt::Display for AliasRelationDirection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AliasRelationDirection::Equate => write!(f, " == "), + AliasRelationDirection::Subtype => write!(f, " <: "), + } + } } /// The crate outlives map is computed during typeck and contains the @@ -976,11 +992,11 @@ impl<'tcx> Term<'tcx> { } } - /// This function returns `None` for `AliasKind::Opaque`. + /// This function returns the inner `AliasTy` if this term is a projection. /// /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly /// deal with constants. - pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> { + pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> { match self.unpack() { TermKind::Ty(ty) => match ty.kind() { ty::Alias(kind, alias_ty) => match kind { @@ -1206,7 +1222,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(Clause::Projection(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) @@ -1227,7 +1243,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(Clause::Trait(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) @@ -1249,7 +1265,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) | PredicateKind::Clause(Clause::Projection(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) @@ -2525,7 +2541,7 @@ impl<'tcx> TyCtxt<'tcx> { ident } - // FIXME(vincenzoapalzzo): move the HirId to a LocalDefId + // FIXME(vincenzopalazzo): move the HirId to a LocalDefId pub fn adjust_ident_and_get_scope( self, mut ident: Ident, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fffdbfc9660..e9f8f2e5865 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2847,7 +2847,7 @@ define_print_and_forward_display! { p!("the type `", print(ty), "` is found in the environment") } ty::PredicateKind::Ambiguous => p!("ambiguous"), - ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)), + ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ef643531bb2..c6bb8146795 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -177,7 +177,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { write!(f, "TypeWellFormedFromEnv({:?})", ty) } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), - ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"), + ty::PredicateKind::AliasRelate(t1, t2, dir) => { + write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") + } } } } @@ -250,6 +252,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::AliasKind, + crate::ty::AliasRelationDirection, crate::ty::Placeholder<crate::ty::BoundRegionKind>, crate::ty::Placeholder<crate::ty::BoundTyKind>, crate::ty::ClosureKind, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 140d1154718..3b775f590a4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -566,41 +566,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Rvalue::Use(Operand::Move(val)) } BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => { - // Consider that the shift overflows if `rhs < 0` or `rhs >= bits`. - // This can be encoded as a single operation as `(rhs & -bits) != 0`. - let (size, _) = ty.int_size_and_signed(self.tcx); - let bits = size.bits(); - debug_assert!(bits.is_power_of_two()); - let mask = !((bits - 1) as u128); - + // For an unsigned RHS, the shift is in-range for `rhs < bits`. + // For a signed RHS, `IntToInt` cast to the equivalent unsigned + // type and do that same comparison. Because the type is the + // same size, there's no negative shift amount that ends up + // overlapping with valid ones, thus it catches negatives too. + let (lhs_size, _) = ty.int_size_and_signed(self.tcx); let rhs_ty = rhs.ty(&self.local_decls, self.tcx); let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx); - let mask = Operand::const_from_scalar( + + let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() { + ty::Uint(_) => (rhs.to_copy(), rhs_ty), + ty::Int(int_width) => { + let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned()); + let rhs_temp = self.temp(uint_ty, span); + self.cfg.push_assign( + block, + source_info, + rhs_temp, + Rvalue::Cast(CastKind::IntToInt, rhs.to_copy(), uint_ty), + ); + (Operand::Move(rhs_temp), uint_ty) + } + _ => unreachable!("only integers are shiftable"), + }; + + // This can't overflow because the largest shiftable types are 128-bit, + // which fits in `u8`, the smallest possible `unsigned_ty`. + // (And `from_uint` will `bug!` if that's ever no longer true.) + let lhs_bits = Operand::const_from_scalar( self.tcx, - rhs_ty, - Scalar::from_uint(rhs_size.truncate(mask), rhs_size), + unsigned_ty, + Scalar::from_uint(lhs_size.bits(), rhs_size), span, ); - let outer_bits = self.temp(rhs_ty, span); - self.cfg.push_assign( - block, - source_info, - outer_bits, - Rvalue::BinaryOp(BinOp::BitAnd, Box::new((rhs.to_copy(), mask))), - ); - - let overflows = self.temp(bool_ty, span); - let zero = self.zero_literal(span, rhs_ty); + let inbounds = self.temp(bool_ty, span); self.cfg.push_assign( block, source_info, - overflows, - Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Move(outer_bits), zero))), + inbounds, + Rvalue::BinaryOp(BinOp::Lt, Box::new((unsigned_rhs, lhs_bits))), ); let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy()); - block = self.assert(block, Operand::Move(overflows), false, overflow_err, span); + block = self.assert(block, Operand::Move(inbounds), true, overflow_err, span); Rvalue::BinaryOp(op, Box::new((lhs, rhs))) } BinOp::Div | BinOp::Rem if ty.is_integral() => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d884ebd9acc..3be0160d561 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -180,7 +180,7 @@ where | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate), + | ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate), } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 362ef693c48..fbac219c322 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -27,7 +27,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; use rustc_middle::{bug, ty}; -use rustc_session::cstore::CrateStore; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -116,33 +115,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !def_id.is_local() { let def_kind = self.cstore().def_kind(def_id); - match def_kind { - DefKind::Mod | DefKind::Enum | DefKind::Trait => { - let def_key = self.cstore().def_key(def_id); - let parent = def_key.parent.map(|index| { - self.get_nearest_non_block_module(DefId { index, krate: def_id.krate }) - }); - let name = if let Some(cnum) = def_id.as_crate_root() { - self.cstore().crate_name(cnum) - } else { - def_key.disambiguated_data.data.get_opt_name().expect("module without name") - }; - - let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); - Some(self.new_module( - parent, - ModuleKind::Def(def_kind, def_id, name), - expn_id, - self.def_span(def_id), - // FIXME: Account for `#[no_implicit_prelude]` attributes. - parent.map_or(false, |module| module.no_implicit_prelude), - )) - } - _ => None, + if let DefKind::Mod | DefKind::Enum | DefKind::Trait = def_kind { + let parent = self + .tcx + .opt_parent(def_id) + .map(|parent_id| self.get_nearest_non_block_module(parent_id)); + let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); + return Some(self.new_module( + parent, + ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)), + expn_id, + self.def_span(def_id), + // FIXME: Account for `#[no_implicit_prelude]` attributes. + parent.map_or(false, |module| module.no_implicit_prelude), + )); } - } else { - None } + + None } pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1afd8851ce0..6af9dc89e56 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -590,7 +590,6 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { parent_scope: ParentScope<'a>, /// The current set of local scopes for types and values. - /// FIXME #4948: Reuse ribs to avoid allocation. ribs: PerNS<Vec<Rib<'a>>>, /// Previous poped `rib`, only used for diagnostic. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index cd90fd3ef84..939f92d39f0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1168,7 +1168,7 @@ impl<'tcx> Resolver<'_, 'tcx> { if let Some(def_id) = def_id.as_local() { self.item_generics_num_lifetimes[&def_id] } else { - self.cstore().item_generics_num_lifetimes(def_id, self.tcx.sess) + self.tcx.generics_of(def_id).own_counts().lifetimes } } @@ -1906,10 +1906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return v.clone(); } - let attr = self - .cstore() - .item_attrs_untracked(def_id, self.tcx.sess) - .find(|a| a.has_name(sym::rustc_legacy_const_generics))?; + let attr = self.tcx.get_attr(def_id, sym::rustc_legacy_const_generics)?; let mut ret = Vec::new(); for meta in attr.meta_item_list()? { match meta.lit()?.kind { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 37153854f7e..ee35664619f 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -703,7 +703,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => { check_consistency(self, &path, path_span, kind, initial_res, res) } - path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => { + path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => { let mut suggestion = None; let (span, label) = if let PathResult::Failed { span, label, .. } = path_res { // try to suggest if it's not a macro, maybe a function diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 95412922357..75b304cce4e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -223,9 +223,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(lhs, rhs) => { - self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs) }) - } + ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self + .compute_alias_relate_goal(Goal { + param_env, + predicate: (lhs, rhs, direction), + }), } } else { let kind = self.infcx.instantiate_binder_with_placeholders(kind); @@ -457,6 +459,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }) } + #[instrument(level = "debug", skip(self, param_env), ret)] + pub(super) fn sub<T: ToTrace<'tcx>>( + &mut self, + param_env: ty::ParamEnv<'tcx>, + sub: T, + sup: T, + ) -> Result<(), NoSolution> { + self.infcx + .at(&ObligationCause::dummy(), param_env) + .sub(DefineOpaqueTypes::No, sub, sup) + .map(|InferOk { value: (), obligations }| { + self.add_goals(obligations.into_iter().map(|o| o.into())); + }) + .map_err(|e| { + debug!(?e, "failed to subtype"); + NoSolution + }) + } + /// Equates two values returning the nested goals without adding them /// to the nested goals of the `EvalCtxt`. /// diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 38120b9760f..01f171762ab 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -73,7 +73,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } - ty::PredicateKind::AliasEq(_, _) => { + ty::PredicateKind::AliasRelate(_, _, _) => { FulfillmentErrorCode::CodeProjectionError( MismatchedProjectionTypes { err: TypeError::Mismatch }, ) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 606c2eaa510..4c87d36ca0d 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -17,7 +17,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -101,11 +100,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // That won't actually reflect in the query response, so it seems moot. self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { - let InferOk { value: (), obligations } = self - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?; - self.add_goals(obligations.into_iter().map(|pred| pred.into())); + self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } @@ -156,55 +151,94 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } #[instrument(level = "debug", skip(self), ret)] - fn compute_alias_eq_goal( + fn compute_alias_relate_goal( &mut self, - goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>)>, + goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); + // We may need to invert the alias relation direction if dealing an alias on the RHS. + enum Invert { + No, + Yes, + } + let evaluate_normalizes_to = + |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| { + debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); + let result = ecx.probe(|ecx| { + let other = match direction { + // This is purely an optimization. + ty::AliasRelationDirection::Equate => other, + + ty::AliasRelationDirection::Subtype => { + let fresh = ecx.next_term_infer_of_kind(other); + let (sub, sup) = match invert { + Invert::No => (fresh, other), + Invert::Yes => (other, fresh), + }; + ecx.sub(goal.param_env, sub, sup)?; + fresh + } + }; + ecx.add_goal(goal.with( + tcx, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: alias, + term: other, + }), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); + debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); + result + }; - let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| { - debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); - let r = ecx.probe(|ecx| { - ecx.add_goal(goal.with( - tcx, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: alias, - term: other, - }), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }); - debug!("evaluate_normalizes_to(..) -> {:?}", r); - r - }; + let (lhs, rhs, direction) = goal.predicate; - if goal.predicate.0.is_infer() || goal.predicate.1.is_infer() { + if lhs.is_infer() || rhs.is_infer() { bug!( - "`AliasEq` goal with an infer var on lhs or rhs which should have been instantiated" + "`AliasRelate` goal with an infer var on lhs or rhs which should have been instantiated" ); } - match ( - goal.predicate.0.to_alias_term_no_opaque(tcx), - goal.predicate.1.to_alias_term_no_opaque(tcx), - ) { - (None, None) => bug!("`AliasEq` goal without an alias on either lhs or rhs"), - (Some(alias), None) => evaluate_normalizes_to(self, alias, goal.predicate.1), - (None, Some(alias)) => evaluate_normalizes_to(self, alias, goal.predicate.0), - (Some(alias_lhs), Some(alias_rhs)) => { - debug!("compute_alias_eq_goal: both sides are aliases"); + match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) { + (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"), - let mut candidates = Vec::with_capacity(3); + // RHS is not a projection, only way this is true is if LHS normalizes-to RHS + (Some(alias_lhs), None) => { + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No) + } - // Evaluate all 3 potential candidates for the alias' being equal - candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1)); - candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0)); - candidates.push(self.probe(|ecx| { - debug!("compute_alias_eq_goal: alias defids are equal, equating substs"); - ecx.eq(goal.param_env, alias_lhs, alias_rhs)?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - })); + // LHS is not a projection, only way this is true is if RHS normalizes-to LHS + (None, Some(alias_rhs)) => { + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes) + } + (Some(alias_lhs), Some(alias_rhs)) => { + debug!("compute_alias_relate_goal: both sides are aliases"); + + let candidates = vec![ + // LHS normalizes-to RHS + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No), + // RHS normalizes-to RHS + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes), + // Relate via substs + self.probe(|ecx| { + debug!( + "compute_alias_relate_goal: alias defids are equal, equating substs" + ); + + match direction { + ty::AliasRelationDirection::Equate => { + ecx.eq(goal.param_env, alias_lhs, alias_rhs)?; + } + ty::AliasRelationDirection::Subtype => { + ecx.sub(goal.param_env, alias_lhs, alias_rhs)?; + } + } + + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }), + ]; debug!(?candidates); self.try_merge_responses(candidates.into_iter()) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index dbf6775afc2..6b3a59b1ed5 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -832,7 +832,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // the `ParamEnv`. ty::PredicateKind::WellFormed(..) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs index 1174efdbfa8..13607b9079a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs @@ -92,6 +92,11 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { } impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> { + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): We really should get rid of this relation. + ty::AliasRelationDirection::Equate + } + fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) { // FIXME(deferred_projection_equality) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 41ffaeeac1c..617d53b609d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1276,9 +1276,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { "TypeWellFormedFromEnv predicate should only exist in the environment" ), - ty::PredicateKind::AliasEq(..) => span_bug!( + ty::PredicateKind::AliasRelate(..) => span_bug!( span, - "AliasEq predicate should never be the predicate cause of a SelectionError" + "AliasRelate predicate should never be the predicate cause of a SelectionError" ), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b501840b926..af108ab6f30 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -212,7 +212,7 @@ pub trait TypeErrCtxtExt<'tcx> { fn extract_callable_info( &self, - hir_id: HirId, + body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, found: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)>; @@ -909,9 +909,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred.self_ty(), ); - let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id); let Some((def_id_or_name, output, inputs)) = self.extract_callable_info( - body_hir_id, + obligation.cause.body_id, obligation.param_env, self_ty, ) else { return false; }; @@ -1113,10 +1112,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { /// Extracts information about a callable type for diagnostics. This is a /// heuristic -- it doesn't necessarily mean that a type is always callable, /// because the callable type must also be well-formed to be called. - // FIXME(vincenzopalazzo): move the HirId to a LocalDefId fn extract_callable_info( &self, - hir_id: HirId, + body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, found: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> { @@ -1168,7 +1166,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }) } ty::Param(param) => { - let generics = self.tcx.generics_of(hir_id.owner.to_def_id()); + let generics = self.tcx.generics_of(body_id); let name = if generics.count() > param.index as usize && let def = generics.param_at(param.index as usize, self.tcx) && matches!(def.kind, ty::GenericParamDefKind::Type { .. }) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 23754480fcf..07e31e87bfb 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -361,8 +361,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } }, Some(pred) => match pred { @@ -630,8 +630,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 038f8964471..5d2af5ff33c 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -335,7 +335,7 @@ fn predicate_references_self<'tcx>( has_self_ty(&ty.into()).then_some(sp) } - ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"), + ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"), ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) @@ -395,7 +395,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b8758ad9323..bffefdf359a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -977,8 +977,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d498af359c5..ec5bd982a3c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -191,8 +191,8 @@ pub fn predicate_obligations<'tcx>( ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("We should only wf check where clauses and `AliasEq` is not a `Clause`") + ty::PredicateKind::AliasRelate(..) => { + bug!("We should only wf check where clauses and `AliasRelate` is not a `Clause`") } } @@ -936,7 +936,7 @@ pub(crate) fn required_region_bounds<'tcx>( | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( ref t, diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 60e22d1001c..0e9bccba8d4 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -119,7 +119,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<' }, ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) @@ -215,7 +215,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi // some of these in terms of chalk operations. ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Ambiguous @@ -652,7 +652,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<' ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) @@ -787,7 +787,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index ddd4ca1436c..f5bba14d2fb 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -86,7 +86,7 @@ fn compute_implied_outlives_bounds<'tcx>( if obligation.predicate.has_non_region_infer() { match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Projection(..)) - | ty::PredicateKind::AliasEq(..) => { + | ty::PredicateKind::AliasRelate(..) => { ocx.register_obligation(obligation.clone()); } _ => {} @@ -110,7 +110,7 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} // We need to search through *all* WellFormed predicates diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index f0597f19225..126a494f34f 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -61,7 +61,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 562f5bffba3..bf0bc202852 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -386,10 +386,6 @@ fn associated_type_for_impl_trait_in_impl( opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), }); - // Copy param_env of the containing function. The synthesized associated type doesn't have - // extra predicates to assume. - impl_assoc_ty.param_env(tcx.param_env(impl_fn_def_id)); - // Copy visility of the containing function. impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id)); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 70686eefbca..50aeb7f440f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -130,7 +130,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should // at least be making sure that the generics in RPITITs and their parent fn don't // get out of alignment, or else we do actually need to substitute these predicates. - if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) { + if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) + | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) + { predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates; } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5a991e03dee..8b23fbc7583 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -432,6 +432,17 @@ impl IntTy { _ => *self, } } + + pub fn to_unsigned(self) -> UintTy { + match self { + IntTy::Isize => UintTy::Usize, + IntTy::I8 => UintTy::U8, + IntTy::I16 => UintTy::U16, + IntTy::I32 => UintTy::U32, + IntTy::I64 => UintTy::U64, + IntTy::I128 => UintTy::U128, + } + } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] @@ -479,6 +490,17 @@ impl UintTy { _ => *self, } } + + pub fn to_signed(self) -> IntTy { + match self { + UintTy::Usize => IntTy::Isize, + UintTy::U8 => IntTy::I8, + UintTy::U16 => IntTy::I16, + UintTy::U32 => IntTy::I32, + UintTy::U64 => IntTy::I64, + UintTy::U128 => IntTy::I128, + } + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 64fc1c0c277..3061f76df04 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -49,6 +49,8 @@ //! //! The input to the [`mir!`] macro is: //! +//! - An optional return type annotation in the form of `type RET = ...;`. This may be required +//! if the compiler cannot infer the type of RET. //! - A possibly empty list of local declarations. Locals can also be declared inline on //! assignments via `let`. Type inference generally works. Shadowing does not. //! - A list of basic blocks. The first of these is the start block and is where execution begins. @@ -124,6 +126,18 @@ //! } //! ) //! } +//! +//! #[custom_mir(dialect = "runtime", phase = "optimized")] +//! fn annotated_return_type() -> (i32, bool) { +//! mir!( +//! type RET = (i32, bool); +//! { +//! RET.0 = 1; +//! RET.1 = true; +//! Return() +//! } +//! ) +//! } //! ``` //! //! We can also set off compilation failures that happen in sufficiently late stages of the @@ -342,6 +356,7 @@ define!( #[rustc_macro_transparency = "transparent"] pub macro mir { ( + $(type RET = $ret_ty:ty ;)? $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* { @@ -362,7 +377,7 @@ pub macro mir { { // Now all locals #[allow(non_snake_case)] - let RET; + let RET $(: $ret_ty)?; $( let $local_decl $(: $local_decl_ty)? ; )* diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 94630e40f3c..36f9aaa595d 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/104748 +Last change is for: https://github.com/rust-lang/rust/pull/109373 diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index dff46b500e3..f27db5c91e2 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -309,6 +309,7 @@ impl Step for Llvm { cfg.out_dir(&out_dir) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) + .define("LLVM_UNREACHABLE_OPTIMIZE", "OFF") .define("LLVM_ENABLE_PLUGINS", plugins) .define("LLVM_TARGETS_TO_BUILD", llvm_targets) .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 9c550b2d728..6fd113fcfd8 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.14.4 \ No newline at end of file +0.14.5 \ No newline at end of file diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2e1f456f50e..c00fa5994bf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -324,7 +324,7 @@ pub(crate) fn clean_predicate<'tcx>( ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Subtype(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 95528e70e35..7d578b5c775 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -217,7 +217,7 @@ ul.all-items { a.anchor, .small-section-header a, #source-sidebar a, -pre.rust a, +.rust a, .sidebar h2 a, .sidebar h3 a, .mobile-topbar h2 a, @@ -228,43 +228,43 @@ h1 a, color: var(--main-color); } -.content span.enum, .content a.enum, -.content span.struct, .content a.struct, -.content span.union, .content a.union, -.content span.primitive, .content a.primitive, -.content span.type, .content a.type, -.content span.foreigntype, .content a.foreigntype { +span.enum, a.enum, +span.struct, a.struct, +span.union, a.union, +span.primitive, a.primitive, +span.type, a.type, +span.foreigntype, a.foreigntype { color: var(--type-link-color); } -.content span.trait, .content a.trait, -.content span.traitalias, .content a.traitalias { +span.trait, a.trait, +span.traitalias, a.traitalias { color: var(--trait-link-color); } -.content span.associatedtype, .content a.associatedtype, -.content span.constant, .content a.constant, -.content span.static, .content a.static { +span.associatedtype, a.associatedtype, +span.constant, a.constant, +span.static, a.static { color: var(--assoc-item-link-color); } -.content span.fn, .content a.fn, -.content span.method, .content a.method, -.content span.tymethod, .content a.tymethod { +span.fn, a.fn, +span.method, a.method, +span.tymethod, a.tymethod { color: var(--function-link-color); } -.content span.attr, .content a.attr, -.content span.derive, .content a.derive, -.content span.macro, .content a.macro { +span.attr, a.attr, +span.derive, a.derive, +span.macro, a.macro { color: var(--macro-link-color); } -.content span.mod, .content a.mod { +span.mod, a.mod { color: var(--mod-link-color); } -.content span.keyword, .content a.keyword { +span.keyword, a.keyword { color: var(--keyword-link-color); } @@ -713,7 +713,7 @@ h2.small-section-header > .anchor { } .main-heading a:hover, -.example-wrap > pre.rust a:hover, +.example-wrap > .rust a:hover, .all-items a:hover, .docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, .docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, 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 24403e8b6f3..58f7742ab87 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 @@ -37,7 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"), + ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 2ade22c209f..67a4df19fcc 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -29,6 +29,7 @@ pub fn filter_dirs(path: &Path) -> bool { // Filter RLS output directories "target/rls", "src/bootstrap/target", + "vendor", ]; skip.iter().any(|p| path.ends_with(p)) } diff --git a/tests/codegen/auxiliary/static_dllimport_aux.rs b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs index afb0dc42f44..afb0dc42f44 100644 --- a/tests/codegen/auxiliary/static_dllimport_aux.rs +++ b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs diff --git a/tests/codegen/issue-103285-ptr-addr-overflow-check.rs b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs index a3499babea2..a3499babea2 100644 --- a/tests/codegen/issue-103285-ptr-addr-overflow-check.rs +++ b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs diff --git a/tests/codegen/issue-103840.rs b/tests/codegen/issues/issue-103840.rs index f19d7031bb3..f19d7031bb3 100644 --- a/tests/codegen/issue-103840.rs +++ b/tests/codegen/issues/issue-103840.rs diff --git a/tests/codegen/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs index d54ac9e33bc..d54ac9e33bc 100644 --- a/tests/codegen/issue-105386-ub-in-debuginfo.rs +++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs diff --git a/tests/codegen/issue-13018.rs b/tests/codegen/issues/issue-13018.rs index b70ea1f48c8..b70ea1f48c8 100644 --- a/tests/codegen/issue-13018.rs +++ b/tests/codegen/issues/issue-13018.rs diff --git a/tests/codegen/issue-15953.rs b/tests/codegen/issues/issue-15953.rs index 28d28428904..28d28428904 100644 --- a/tests/codegen/issue-15953.rs +++ b/tests/codegen/issues/issue-15953.rs diff --git a/tests/codegen/issue-27130.rs b/tests/codegen/issues/issue-27130.rs index e5ee94e1f45..e5ee94e1f45 100644 --- a/tests/codegen/issue-27130.rs +++ b/tests/codegen/issues/issue-27130.rs diff --git a/tests/codegen/issue-32031.rs b/tests/codegen/issues/issue-32031.rs index abef92c19b6..abef92c19b6 100644 --- a/tests/codegen/issue-32031.rs +++ b/tests/codegen/issues/issue-32031.rs diff --git a/tests/codegen/issue-32364.rs b/tests/codegen/issues/issue-32364.rs index 85493a4bb73..85493a4bb73 100644 --- a/tests/codegen/issue-32364.rs +++ b/tests/codegen/issues/issue-32364.rs diff --git a/tests/codegen/issue-34634.rs b/tests/codegen/issues/issue-34634.rs index f53fa240cd1..f53fa240cd1 100644 --- a/tests/codegen/issue-34634.rs +++ b/tests/codegen/issues/issue-34634.rs diff --git a/tests/codegen/issue-34947-pow-i32.rs b/tests/codegen/issues/issue-34947-pow-i32.rs index 653da8e8b5f..653da8e8b5f 100644 --- a/tests/codegen/issue-34947-pow-i32.rs +++ b/tests/codegen/issues/issue-34947-pow-i32.rs diff --git a/tests/codegen/issue-37945.rs b/tests/codegen/issues/issue-37945.rs index fe54375bbf6..fe54375bbf6 100644 --- a/tests/codegen/issue-37945.rs +++ b/tests/codegen/issues/issue-37945.rs diff --git a/tests/codegen/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs index 1a3923f1bb1..1a3923f1bb1 100644 --- a/tests/codegen/issue-44056-macos-tls-align.rs +++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs diff --git a/tests/codegen/issue-45222.rs b/tests/codegen/issues/issue-45222.rs index e9b05e648b4..e9b05e648b4 100644 --- a/tests/codegen/issue-45222.rs +++ b/tests/codegen/issues/issue-45222.rs diff --git a/tests/codegen/issue-45466.rs b/tests/codegen/issues/issue-45466.rs index c7954276777..c7954276777 100644 --- a/tests/codegen/issue-45466.rs +++ b/tests/codegen/issues/issue-45466.rs diff --git a/tests/codegen/issue-45964-bounds-check-slice-pos.rs b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs index 1daa213fc82..1daa213fc82 100644 --- a/tests/codegen/issue-45964-bounds-check-slice-pos.rs +++ b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs diff --git a/tests/codegen/issue-47278.rs b/tests/codegen/issues/issue-47278.rs index 9076274f45e..9076274f45e 100644 --- a/tests/codegen/issue-47278.rs +++ b/tests/codegen/issues/issue-47278.rs diff --git a/tests/codegen/issue-47442.rs b/tests/codegen/issues/issue-47442.rs index 6944336d335..6944336d335 100644 --- a/tests/codegen/issue-47442.rs +++ b/tests/codegen/issues/issue-47442.rs diff --git a/tests/codegen/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs index 4dc9ebfebbc..4dc9ebfebbc 100644 --- a/tests/codegen/issue-56267-2.rs +++ b/tests/codegen/issues/issue-56267-2.rs diff --git a/tests/codegen/issue-56267.rs b/tests/codegen/issues/issue-56267.rs index 7bdd2577998..7bdd2577998 100644 --- a/tests/codegen/issue-56267.rs +++ b/tests/codegen/issues/issue-56267.rs diff --git a/tests/codegen/issue-56927.rs b/tests/codegen/issues/issue-56927.rs index 044d721814b..044d721814b 100644 --- a/tests/codegen/issue-56927.rs +++ b/tests/codegen/issues/issue-56927.rs diff --git a/tests/codegen/issue-58881.rs b/tests/codegen/issues/issue-58881.rs index 00f8953d949..00f8953d949 100644 --- a/tests/codegen/issue-58881.rs +++ b/tests/codegen/issues/issue-58881.rs diff --git a/tests/codegen/issue-59352.rs b/tests/codegen/issues/issue-59352.rs index d271fe027e3..d271fe027e3 100644 --- a/tests/codegen/issue-59352.rs +++ b/tests/codegen/issues/issue-59352.rs diff --git a/tests/codegen/issue-69101-bounds-check.rs b/tests/codegen/issues/issue-69101-bounds-check.rs index a3aca3a2912..a3aca3a2912 100644 --- a/tests/codegen/issue-69101-bounds-check.rs +++ b/tests/codegen/issues/issue-69101-bounds-check.rs diff --git a/tests/codegen/issue-73031.rs b/tests/codegen/issues/issue-73031.rs index a09c4bcfbea..a09c4bcfbea 100644 --- a/tests/codegen/issue-73031.rs +++ b/tests/codegen/issues/issue-73031.rs diff --git a/tests/codegen/issue-73338-effecient-cmp.rs b/tests/codegen/issues/issue-73338-effecient-cmp.rs index 85c2bbfd040..85c2bbfd040 100644 --- a/tests/codegen/issue-73338-effecient-cmp.rs +++ b/tests/codegen/issues/issue-73338-effecient-cmp.rs diff --git a/tests/codegen/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs index 8d07a67a1b4..8d07a67a1b4 100644 --- a/tests/codegen/issue-73396-bounds-check-after-position.rs +++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs diff --git a/tests/codegen/issue-73827-bounds-check-index-in-subexpr.rs b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs index 1ad05906e21..1ad05906e21 100644 --- a/tests/codegen/issue-73827-bounds-check-index-in-subexpr.rs +++ b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs diff --git a/tests/codegen/issue-75525-bounds-checks.rs b/tests/codegen/issues/issue-75525-bounds-checks.rs index 2d363d8f73b..2d363d8f73b 100644 --- a/tests/codegen/issue-75525-bounds-checks.rs +++ b/tests/codegen/issues/issue-75525-bounds-checks.rs diff --git a/tests/codegen/issue-75546.rs b/tests/codegen/issues/issue-75546.rs index 470a9e04096..470a9e04096 100644 --- a/tests/codegen/issue-75546.rs +++ b/tests/codegen/issues/issue-75546.rs diff --git a/tests/codegen/issue-75659.rs b/tests/codegen/issues/issue-75659.rs index 9394868c08d..9394868c08d 100644 --- a/tests/codegen/issue-75659.rs +++ b/tests/codegen/issues/issue-75659.rs diff --git a/tests/codegen/issue-77812.rs b/tests/codegen/issues/issue-77812.rs index 4cc82414546..4cc82414546 100644 --- a/tests/codegen/issue-77812.rs +++ b/tests/codegen/issues/issue-77812.rs diff --git a/tests/codegen/issue-81408-dllimport-thinlto-windows.rs b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs index 0b6ab4f7ecb..0b6ab4f7ecb 100644 --- a/tests/codegen/issue-81408-dllimport-thinlto-windows.rs +++ b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs diff --git a/tests/codegen/issue-84268.rs b/tests/codegen/issues/issue-84268.rs index 7ca19544700..7ca19544700 100644 --- a/tests/codegen/issue-84268.rs +++ b/tests/codegen/issues/issue-84268.rs diff --git a/tests/codegen/issue-85872-multiple-reverse.rs b/tests/codegen/issues/issue-85872-multiple-reverse.rs index 591a1aca747..591a1aca747 100644 --- a/tests/codegen/issue-85872-multiple-reverse.rs +++ b/tests/codegen/issues/issue-85872-multiple-reverse.rs diff --git a/tests/codegen/issue-86106.rs b/tests/codegen/issues/issue-86106.rs index 9ccbcb24f56..9ccbcb24f56 100644 --- a/tests/codegen/issue-86106.rs +++ b/tests/codegen/issues/issue-86106.rs diff --git a/tests/codegen/issue-96274.rs b/tests/codegen/issues/issue-96274.rs index 28bfcce0d7b..28bfcce0d7b 100644 --- a/tests/codegen/issue-96274.rs +++ b/tests/codegen/issues/issue-96274.rs diff --git a/tests/codegen/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs index 0413ed6b26f..0413ed6b26f 100644 --- a/tests/codegen/issue-96497-slice-size-nowrap.rs +++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs diff --git a/tests/codegen/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs index 12ace5fff6b..12ace5fff6b 100644 --- a/tests/codegen/issue-98156-const-arg-temp-lifetime.rs +++ b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs diff --git a/tests/codegen/issue-98294-get-mut-copy-from-slice-opt.rs b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs index 7da29cd7952..7da29cd7952 100644 --- a/tests/codegen/issue-98294-get-mut-copy-from-slice-opt.rs +++ b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs index aa6589dc35b..b3c3483fea9 100644 --- a/tests/codegen/vec-shrink-panik.rs +++ b/tests/codegen/vec-shrink-panik.rs @@ -1,3 +1,8 @@ +// revisions: old new +// LLVM 17 realizes double panic is not possible and doesn't generate calls +// to panic_cannot_unwind. +// [old]ignore-llvm-version: 17 - 99 +// [new]min-llvm-version: 17 // compile-flags: -O // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] @@ -18,11 +23,11 @@ pub fn shrink_to_fit(vec: &mut Vec<u32>) { pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> { // CHECK-NOT: panic - // Call to panic_cannot_unwind in case of double-panic is expected, - // but other panics are not. + // Call to panic_cannot_unwind in case of double-panic is expected + // on LLVM 16 and older, but other panics are not. // CHECK: cleanup - // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind - // CHECK-NEXT: panic_cannot_unwind + // old-NEXT: ; call core::panicking::panic_cannot_unwind + // old-NEXT: panic_cannot_unwind // CHECK-NOT: panic vec.into_boxed_slice() @@ -34,14 +39,14 @@ pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> { // CHECK-NOT: panic // Call to panic_cannot_unwind in case of double-panic is expected, - // but other panics are not. + // on LLVM 16 and older, but other panics are not. // CHECK: cleanup - // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind - // CHECK-NEXT: panic_cannot_unwind + // old-NEXT: ; call core::panicking::panic_cannot_unwind + // old-NEXT: panic_cannot_unwind // CHECK-NOT: panic iter.iter().copied().collect() } -// CHECK: ; core::panicking::panic_cannot_unwind -// CHECK: declare void @{{.*}}panic_cannot_unwind +// old: ; core::panicking::panic_cannot_unwind +// old: declare void @{{.*}}panic_cannot_unwind diff --git a/tests/mir-opt/building/custom/composite_return.rs b/tests/mir-opt/building/custom/composite_return.rs new file mode 100644 index 00000000000..701d6b1ab71 --- /dev/null +++ b/tests/mir-opt/building/custom/composite_return.rs @@ -0,0 +1,21 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR composite_return.tuple.built.after.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn tuple() -> (i32, bool) { + mir!( + type RET = (i32, bool); + { + RET.0 = 1; + RET.1 = true; + Return() + } + ) +} + +fn main() { + assert_eq!(tuple(), (1, true)); +} diff --git a/tests/mir-opt/building/custom/composite_return.tuple.built.after.mir b/tests/mir-opt/building/custom/composite_return.tuple.built.after.mir new file mode 100644 index 00000000000..d159c1a655e --- /dev/null +++ b/tests/mir-opt/building/custom/composite_return.tuple.built.after.mir @@ -0,0 +1,11 @@ +// MIR for `tuple` after built + +fn tuple() -> (i32, bool) { + let mut _0: (i32, bool); // return place in scope 0 at $DIR/composite_return.rs:+0:15: +0:26 + + bb0: { + (_0.0: i32) = const 1_i32; // scope 0 at $DIR/composite_return.rs:+4:13: +4:22 + (_0.1: bool) = const true; // scope 0 at $DIR/composite_return.rs:+5:13: +5:25 + return; // scope 0 at $DIR/composite_return.rs:+6:13: +6:21 + } +} diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs new file mode 100644 index 00000000000..4b63a00a304 --- /dev/null +++ b/tests/mir-opt/building/shifts.rs @@ -0,0 +1,20 @@ +// compile-flags: -C debug-assertions=yes + +// EMIT_MIR shifts.shift_signed.built.after.mir +fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) { + ( + [small >> a, small >> b, small >> c], + [big << a, big << b, big << c], + ) +} + +// EMIT_MIR shifts.shift_unsigned.built.after.mir +fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) { + ( + [small >> a, small >> b, small >> c], + [big << a, big << b, big << c], + ) +} + +fn main() { +} diff --git a/tests/mir-opt/building/shifts.shift_signed.built.after.mir b/tests/mir-opt/building/shifts.shift_signed.built.after.mir new file mode 100644 index 00000000000..028777cefdd --- /dev/null +++ b/tests/mir-opt/building/shifts.shift_signed.built.after.mir @@ -0,0 +1,147 @@ +// MIR for `shift_signed` after built + +fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; 3]) { + debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:17: +0:22 + debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:28: +0:31 + debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:39: +0:40 + debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:46: +0:47 + debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:54: +0:55 + let mut _0: ([i8; 3], [u128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:66: +0:86 + let mut _6: [i8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45 + let mut _7: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _8: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 + let mut _9: i8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 + let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _12: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _13: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 + let mut _14: i32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 + let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _17: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _18: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 + let mut _19: i128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 + let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _22: [u128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 + let mut _23: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _24: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 + let mut _25: i8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 + let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _28: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _29: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 + let mut _30: i32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 + let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _33: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _34: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 + let mut _35: i128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 + let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + + bb0: { + StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _10 = _9 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _11 = Lt(move _10, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + } + + bb1: { + _7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + _13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _15 = _14 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + _16 = Lt(move _15, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + } + + bb2: { + _12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + _18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _20 = _19 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _21 = Lt(move _20, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + } + + bb3: { + _17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + _24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _26 = _25 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + _27 = Lt(move _26, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + } + + bb4: { + _23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + _29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _31 = _30 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _32 = Lt(move _31, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + } + + bb5: { + _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + _34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _36 = _35 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _37 = Lt(move _36, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + } + + bb6: { + _33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 + StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 + } + + bb7 (cleanup): { + resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2 + } +} diff --git a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir new file mode 100644 index 00000000000..04da2d20d24 --- /dev/null +++ b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir @@ -0,0 +1,135 @@ +// MIR for `shift_unsigned` after built + +fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i128; 3]) { + debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:19: +0:24 + debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:30: +0:33 + debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:41: +0:42 + debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:48: +0:49 + debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:56: +0:57 + let mut _0: ([u8; 3], [i128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:68: +0:88 + let mut _6: [u8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45 + let mut _7: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _8: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 + let mut _9: u8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 + let mut _10: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _11: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _12: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 + let mut _13: u32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 + let mut _14: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _15: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _16: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 + let mut _17: u128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 + let mut _18: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _19: [i128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 + let mut _20: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _21: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 + let mut _22: u8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 + let mut _23: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _24: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _25: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 + let mut _26: u32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 + let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _28: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _29: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 + let mut _30: u128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 + let mut _31: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + + bb0: { + StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _10 = Lt(_9, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(move _10, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + } + + bb1: { + _7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageLive(_11); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + _12 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _13 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _14 = Lt(_13, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(move _14, "attempt to shift right by `{}`, which would overflow", _13) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + } + + bb2: { + _11 = Shr(move _12, move _13); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageLive(_15); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageLive(_16); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + _16 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _17 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _18 = Lt(_17, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + } + + bb3: { + _15 = Shr(move _16, move _17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + StorageDead(_16); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _6 = [move _7, move _11, move _15]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageDead(_15); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_11); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageLive(_19); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageLive(_20); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_21); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + _21 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _22 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _23 = Lt(_22, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(move _23, "attempt to shift left by `{}`, which would overflow", _22) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + } + + bb4: { + _20 = Shl(move _21, move _22); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageDead(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageDead(_21); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + _25 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + StorageLive(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _26 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _27 = Lt(_26, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(move _27, "attempt to shift left by `{}`, which would overflow", _26) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + } + + bb5: { + _24 = Shl(move _25, move _26); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageDead(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + _29 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _30 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _31 = Lt(_30, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(move _31, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + } + + bb6: { + _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _19 = [move _20, move _24, move _28]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_20); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _0 = (move _6, move _19); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 + StorageDead(_19); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 + } + + bb7 (cleanup): { + resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2 + } +} diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff index fb0b3866e69..b377a65b964 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff @@ -12,9 +12,9 @@ let mut _7: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 let mut _8: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 let mut _9: u32; // in scope 0 at $DIR/issue_101973.rs:+1:33: +1:39 - let mut _10: i32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + let mut _10: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 let mut _11: bool; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 - let mut _12: i32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + let mut _12: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 let mut _13: bool; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17 debug x => _1; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14 @@ -43,24 +43,24 @@ StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- _10 = BitAnd(const 8_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- _11 = Ne(move _10, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- assert(!move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ _10 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ _11 = const false; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ assert(!const false, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- _10 = const 8_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- _11 = Lt(move _10, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ _10 = const 8_u32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ _11 = const true; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 } bb1: { _8 = Shr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 _7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageDead(_8); // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52 -- _12 = BitAnd(const 1_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -- _13 = Ne(move _12, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -- assert(!move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ _12 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ _13 = const false; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ assert(!const false, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- _12 = const 1_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- _13 = Lt(move _12, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ _12 = const 1_u32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ _13 = const true; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 } bb2: { diff --git a/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml new file mode 100644 index 00000000000..0ebb96d7870 --- /dev/null +++ b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml @@ -0,0 +1,51 @@ +// This test ensures that the "Auto-hide item contents for large items" setting is working as +// expected. + +// We need to disable this check because `implementors/test_docs/trait.Iterator.js` doesn't exist. +fail-on-request-error: false + +define-function: ( + "check-setting", + (storage_value, setting_attribute_value, toggle_attribute_value), + block { + assert-local-storage: {"rustdoc-auto-hide-large-items": |storage_value|} + click: "#settings-menu" + wait-for: "#settings" + assert-property: ("#auto-hide-large-items", {"checked": |setting_attribute_value|}) + assert-attribute: (".item-decl .type-contents-toggle", {"open": |toggle_attribute_value|}) + } +) + +goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html" + +// We check that the setting is enabled by default and is working. +call-function: ("check-setting", { + "storage_value": null, + "setting_attribute_value": "true", + "toggle_attribute_value": null, +}) + +// Now we change its value. +click: "#auto-hide-large-items" +assert-local-storage: {"rustdoc-auto-hide-large-items": "false"} + +// We check that the changes were applied as expected. +reload: + +call-function: ("check-setting", { + "storage_value": "false", + "setting_attribute_value": "false", + "toggle_attribute_value": "", +}) + +// And now we re-enable the setting. +click: "#auto-hide-large-items" +assert-local-storage: {"rustdoc-auto-hide-large-items": "true"} + +// And we check everything is back the way it was before. +reload: +call-function: ("check-setting", { + "storage_value": "true", + "setting_attribute_value": "true", + "toggle_attribute_value": null, +}) diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index e396df4e5d1..3d010f18009 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -1,5 +1,7 @@ // edition:2021 // check-pass +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(async_fn_in_trait)] #![allow(incomplete_features)] diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs new file mode 100644 index 00000000000..64317b9d39a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs @@ -0,0 +1,52 @@ +// check-pass +// known-bug: #97156 + +#![feature(const_type_id, generic_const_exprs)] +#![allow(incomplete_features)] + +use std::any::TypeId; +// `One` and `Two` are currently considered equal types, as both +// `One <: Two` and `One :> Two` holds. +type One = for<'a> fn(&'a (), &'a ()); +type Two = for<'a, 'b> fn(&'a (), &'b ()); +trait AssocCt { + const ASSOC: usize; +} +const fn to_usize<T: 'static>() -> usize { + const WHAT_A_TYPE: TypeId = TypeId::of::<One>(); + match TypeId::of::<T>() { + WHAT_A_TYPE => 0, + _ => 1000, + } +} +impl<T: 'static> AssocCt for T { + const ASSOC: usize = to_usize::<T>(); +} + +trait WithAssoc<U> { + type Assoc; +} +impl<T: 'static> WithAssoc<()> for T where [(); <T as AssocCt>::ASSOC]: { + type Assoc = [u8; <T as AssocCt>::ASSOC]; +} + +fn generic<T: 'static, U>(x: <T as WithAssoc<U>>::Assoc) -> <T as WithAssoc<U>>::Assoc +where + [(); <T as AssocCt>::ASSOC]:, + T: WithAssoc<U>, +{ + x +} + + +fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc +where + One: WithAssoc<T>, +{ + let x: <Two as WithAssoc<T>>::Assoc = generic::<One, T>(x); + x +} + +fn main() { + println!("{:?}", unsound::<()>([])); +} diff --git a/tests/ui/impl-trait/nested-return-type2.rs b/tests/ui/impl-trait/nested-return-type2.rs index fe883ce6fc8..e1d5511379e 100644 --- a/tests/ui/impl-trait/nested-return-type2.rs +++ b/tests/ui/impl-trait/nested-return-type2.rs @@ -26,7 +26,6 @@ impl<R: Duh, F: FnMut() -> R> Trait for F { // Lazy TAIT would error out, but we inserted a hack to make it work again, // keeping backwards compatibility. fn foo() -> impl Trait<Assoc = impl Send> { - //~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds || 42 } diff --git a/tests/ui/impl-trait/nested-return-type2.stderr b/tests/ui/impl-trait/nested-return-type2.stderr deleted file mode 100644 index 09ad3bd05c1..00000000000 --- a/tests/ui/impl-trait/nested-return-type2.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds - --> $DIR/nested-return-type2.rs:28:24 - | -LL | type Assoc: Duh; - | --- this associated type bound is unsatisfied for `impl Send` -... -LL | fn foo() -> impl Trait<Assoc = impl Send> { - | ^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> { - | +++++ - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/nested-return-type3.rs b/tests/ui/impl-trait/nested-return-type3.rs index 5a764fc4c28..74b4dae22eb 100644 --- a/tests/ui/impl-trait/nested-return-type3.rs +++ b/tests/ui/impl-trait/nested-return-type3.rs @@ -13,7 +13,6 @@ impl<F: Duh> Trait for F { } fn foo() -> impl Trait<Assoc = impl Send> { - //~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds 42 } diff --git a/tests/ui/impl-trait/nested-return-type3.stderr b/tests/ui/impl-trait/nested-return-type3.stderr deleted file mode 100644 index 632de71aa4c..00000000000 --- a/tests/ui/impl-trait/nested-return-type3.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds - --> $DIR/nested-return-type3.rs:15:24 - | -LL | type Assoc: Duh; - | --- this associated type bound is unsatisfied for `impl Send` -... -LL | fn foo() -> impl Trait<Assoc = impl Send> { - | ^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> { - | +++++ - -warning: 1 warning emitted - diff --git a/tests/ui/traits/new-solver/alias-sub.rs b/tests/ui/traits/new-solver/alias-sub.rs new file mode 100644 index 00000000000..30c1981a92e --- /dev/null +++ b/tests/ui/traits/new-solver/alias-sub.rs @@ -0,0 +1,34 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Trait { + type Assoc: Sized; +} + +impl Trait for &'static str { + type Assoc = &'static str; +} + +// Wrapper is just here to get around stupid `Sized` obligations in mir typeck +struct Wrapper<T: ?Sized>(std::marker::PhantomData<T>); +fn mk<T: Trait>(x: T) -> Wrapper<<T as Trait>::Assoc> { todo!() } + + +trait IsStaticStr {} +impl IsStaticStr for (&'static str,) {} +fn define<T: IsStaticStr>(_: T) {} + +fn foo<'a, T: Trait>() { + let y = Default::default(); + + // `<?0 as Trait>::Assoc <: &'a str` + // In the old solver, this would *equate* the LHS and RHS. + let _: Wrapper<&'a str> = mk(y); + + // ... then later on, we constrain `?0 = &'static str` + // but that should not mean that `'a = 'static`, because + // we should use *sub* above. + define((y,)); +} + +fn main() {} |
