diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs index d41cbf757d7f8..341c50c37f6db 100644 --- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs +++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs @@ -266,10 +266,6 @@ impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 98b41187f114d..f93b9e5af5345 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -309,6 +309,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// Used for remapped captured lifetimes in an existential `impl Trait` type node. + OpaqueLifetime(Symbol), /// An anonymous associated type from an RPITIT. The symbol refers to the name of the method /// that defined the type. AnonAssocTy(Symbol), @@ -445,7 +447,8 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => Some(name), Impl | ForeignMod @@ -465,9 +468,8 @@ impl DefPathData { fn hashed_symbol(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => { - Some(name) - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) + | OpaqueLifetime(name) => Some(name), Impl | ForeignMod @@ -486,9 +488,8 @@ impl DefPathData { pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { - TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { - DefPathDataName::Named(name) - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) + | OpaqueLifetime(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index bbf36fef1ddbe..fb67f2fd22350 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -5,7 +5,7 @@ use std::iter; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; @@ -14,10 +14,10 @@ use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, + TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>( // but found 0" it's confusing, because it looks like there // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. - if trait_params != impl_params { - let span = tcx - .hir_get_generics(impl_m.def_id.expect_local()) - .expect("expected impl item to have generics or else we can't compare them") - .span; - - let mut generics_span = None; - let mut bounds_span = vec![]; - let mut where_span = None; - if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) - && let Some(trait_generics) = trait_node.generics() - { - generics_span = Some(trait_generics.span); - // FIXME: we could potentially look at the impl's bounds to not point at bounds that - // *are* present in the impl. - for p in trait_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + if trait_params == impl_params { + return Ok(()); + } + + if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) { + return Err(guar); + } + + let span = tcx + .hir_get_generics(impl_m.def_id.expect_local()) + .expect("expected impl item to have generics or else we can't compare them") + .span; + + let mut generics_span = None; + let mut bounds_span = vec![]; + let mut where_span = None; + + if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id) + && let Some(trait_generics) = trait_node.generics() + { + generics_span = Some(trait_generics.span); + // FIXME: we could potentially look at the impl's bounds to not point at bounds that + // *are* present in the impl. + for p in trait_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(lt) = b { bounds_span.push(lt.ident.span); } } } + _ => {} } - if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) - && let Some(impl_generics) = impl_node.generics() - { - let mut impl_bounds = 0; - for p in impl_generics.predicates { - if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { - for b in pred.bounds { + } + if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id) + && let Some(impl_generics) = impl_node.generics() + { + let mut impl_bounds = 0; + for p in impl_generics.predicates { + match p.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bounds, + .. + }) + | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + bounds, + .. + }) => { + for b in *bounds { if let hir::GenericBound::Outlives(_) = b { impl_bounds += 1; } } } + _ => {} + } + } + if impl_bounds == bounds_span.len() { + bounds_span = vec![]; + } else if impl_generics.has_where_clause_predicates { + where_span = Some(impl_generics.where_clause_span); + } + } + } + + let reported = tcx + .dcx() + .create_err(LifetimesOrBoundsMismatchOnTrait { + span, + item_kind: impl_m.descr(), + ident: impl_m.ident(tcx), + generics_span, + bounds_span, + where_span, + }) + .emit_unless(delay); + + Err(reported) +} + +#[allow(unused)] +enum LateEarlyMismatch<'tcx> { + EarlyInImpl(DefId, DefId, ty::Region<'tcx>), + LateInImpl(DefId, DefId, ty::Region<'tcx>), +} + +fn check_region_late_boundedness<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: ty::AssocItem, + trait_m: ty::AssocItem, +) -> Option { + if !impl_m.is_fn() { + return None; + } + + let (infcx, param_env) = tcx + .infer_ctxt() + .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id)); + + let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id); + let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args); + let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig); + + let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id); + let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args); + let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig); + + let ocx = ObligationCtxt::new(&infcx); + + // Equate the signatures so that we can infer whether a late-bound param was present where + // an early-bound param was expected, since we replace the late-bound lifetimes with + // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will + // resolve to `ReLateParam` if there is a mismatch. + let Ok(()) = ocx.eq( + &ObligationCause::dummy(), + param_env, + ty::Binder::dummy(trait_m_sig), + ty::Binder::dummy(impl_m_sig), + ) else { + return None; + }; + + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return None; + } + + let mut mismatched = vec![]; + + let impl_generics = tcx.generics_of(impl_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(trait_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::EarlyInImpl( + impl_generics.region_param(ebr, tcx).def_id, + trait_param_def_id, + id_arg.expect_region(), + )); + } + } + + let trait_generics = tcx.generics_of(trait_m.def_id); + for (id_arg, arg) in + std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args) + { + if let ty::GenericArgKind::Lifetime(r) = arg.unpack() + && let ty::ReVar(vid) = r.kind() + && let r = infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(tcx, vid) + && let ty::ReLateParam(ty::LateParamRegion { + kind: ty::LateParamRegionKind::Named(impl_param_def_id, _), + .. + }) = r.kind() + && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind() + { + mismatched.push(LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_generics.region_param(ebr, tcx).def_id, + id_arg.expect_region(), + )); + } + } + + if mismatched.is_empty() { + return None; + } + + let spans: Vec<_> = mismatched + .iter() + .map(|param| { + let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..) + | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param; + tcx.def_span(impl_param_def_id) + }) + .collect(); + + let mut diag = tcx + .dcx() + .struct_span_err(spans, "lifetime parameters do not match the trait definition") + .with_note("lifetime parameters differ in whether they are early- or late-bound") + .with_code(E0195); + for mismatch in mismatched { + match mismatch { + LateEarlyMismatch::EarlyInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, impl_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(impl_param_def_id) + ), + ); } - if impl_bounds == bounds_span.len() { - bounds_span = vec![]; - } else if impl_generics.has_where_clause_predicates { - where_span = Some(impl_generics.where_clause_span); + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); + } + LateEarlyMismatch::LateInImpl( + impl_param_def_id, + trait_param_def_id, + early_bound_region, + ) => { + let mut multispan = MultiSpan::from_spans(vec![ + tcx.def_span(impl_param_def_id), + tcx.def_span(trait_param_def_id), + ]); + multispan + .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl..."); + multispan + .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait..."); + multispan.push_span_label( + tcx.def_span(impl_param_def_id), + format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)), + ); + multispan.push_span_label( + tcx.def_span(trait_param_def_id), + format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)), + ); + if let Some(span) = + find_region_in_predicates(tcx, trait_m.def_id, early_bound_region) + { + multispan.push_span_label( + span, + format!( + "this lifetime bound makes `{}` early-bound", + tcx.item_name(trait_param_def_id) + ), + ); } + diag.span_note( + multispan, + format!( + "`{}` differs between the trait and impl", + tcx.item_name(impl_param_def_id) + ), + ); } } - let reported = tcx - .dcx() - .create_err(LifetimesOrBoundsMismatchOnTrait { - span, - item_kind: impl_m.descr(), - ident: impl_m.ident(tcx), - generics_span, - bounds_span, - where_span, - }) - .emit_unless(delay); - return Err(reported); } - Ok(()) + Some(diag.emit()) +} + +fn find_region_in_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + early_bound_region: ty::Region<'tcx>, +) -> Option { + for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) { + if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() { + return Some(span); + } + } + + struct FindRegion<'tcx>(ty::Region<'tcx>); + impl<'tcx> TypeVisitor> for FindRegion<'tcx> { + type Result = ControlFlow<()>; + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } + } + } + + None } #[instrument(level = "debug", skip(infcx))] diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index a89160785eb12..709446d09cd25 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -14,7 +14,7 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DisambiguatorState; +use rustc_hir::definitions::{DefPathData, DisambiguatorState}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{ self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node, @@ -1470,14 +1470,14 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let mut captures = captures.borrow_mut(); let remapped = *captures.entry(lifetime).or_insert_with(|| { // `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once - // per `resolve_bound_vars` query. This is the only location that creates nested - // lifetime inside a opaque type. `::LifetimeNs(..)` is thus unique + // per `resolve_bound_vars` query. This is the only location that creates + // `OpaqueLifetime` paths. `::OpaqueLifetime(..)` is thus unique // to this query and duplicates within the query are handled by `self.disambiguator`. let feed = self.tcx.create_def( opaque_def_id, - Some(ident.name), - DefKind::LifetimeParam, None, + DefKind::LifetimeParam, + Some(DefPathData::OpaqueLifetime(ident.name)), &mut self.disambiguator, ); feed.def_span(ident.span); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index bf91eb1b8fdac..4419d5dc7d663 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{AmbigArg, HirId}; use rustc_middle::bug; use rustc_middle::ty::{ - self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; @@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> { impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 'tcx> { type Result = ControlFlow; - fn visit_binder>>( + fn visit_binder>>( &mut self, binder: &ty::Binder<'tcx, T>, ) -> Self::Result { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 78233a34c461c..60187abd55897 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -32,6 +32,7 @@ mod gather_locals; mod intrinsicck; mod method; mod op; +mod opaque_types; mod pat; mod place_op; mod rvalue_scopes; @@ -245,9 +246,7 @@ fn typeck_with_inspect<'tcx>( let typeck_results = fcx.resolve_type_vars_in_body(body); - // We clone the defined opaque types during writeback in the new solver - // because we have to use them during normalization. - let _ = fcx.infcx.take_opaque_types(); + fcx.detect_opaque_types_added_during_writeback(); // Consistency check our TypeckResults instance can hold all ItemLocalIds // it will need to hold. diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs new file mode 100644 index 0000000000000..e0224f8c6e1b4 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -0,0 +1,26 @@ +use super::FnCtxt; +impl<'tcx> FnCtxt<'_, 'tcx> { + /// We may in theory add further uses of an opaque after cloning the opaque + /// types storage during writeback when computing the defining uses. + /// + /// Silently ignoring them is dangerous and could result in ICE or even in + /// unsoundness, so we make sure we catch such cases here. There's currently + /// no known code where this actually happens, even with the new solver which + /// does normalize types in writeback after cloning the opaque type storage. + /// + /// FIXME(@lcnr): I believe this should be possible in theory and would like + /// an actual test here. After playing around with this for an hour, I wasn't + /// able to do anything which didn't already try to normalize the opaque before + /// then, either allowing compilation to succeed or causing an ambiguity error. + pub(super) fn detect_opaque_types_added_during_writeback(&self) { + let num_entries = self.checked_opaque_types_storage_entries.take().unwrap(); + for (key, hidden_type) in + self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries) + { + let opaque_type_string = self.tcx.def_path_str(key.def_id); + let msg = format!("unexpected cyclic definition of `{opaque_type_string}`"); + self.dcx().span_delayed_bug(hidden_type.span, msg); + } + let _ = self.take_opaque_types(); + } +} diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 56859eef45f72..26be5fc6d1904 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -1,10 +1,10 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::Deref; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, HirId, HirIdMap, LangItem}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt}; use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::Span; @@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) fulfillment_cx: RefCell>>>, + // Used to detect opaque types uses added after we've already checked them. + // + // See [FnCtxt::detect_opaque_types_added_during_writeback] for more details. + pub(super) checked_opaque_types_storage_entries: Cell>, + /// Some additional `Sized` obligations badly affect type inference. /// These obligations are added in a later stage of typeck. /// Removing these may also cause additional complications, see #101066. @@ -85,12 +90,14 @@ impl<'tcx> TypeckRootCtxt<'tcx> { let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); + let fulfillment_cx = RefCell::new(>::new(&infcx)); TypeckRootCtxt { - typeck_results, - fulfillment_cx: RefCell::new(>::new(&infcx)), infcx, + typeck_results, locals: RefCell::new(Default::default()), + fulfillment_cx, + checked_opaque_types_storage_entries: Cell::new(None), deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8e7ce83044cd2..9be041f75d769 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -535,13 +535,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let tcx = self.tcx(); // We clone the opaques instead of stealing them here as they are still used for // normalization in the next generation trait solver. - // - // FIXME(-Znext-solver): Opaque types defined after this would simply get dropped - // at the end of typeck. While this seems unlikely to happen in practice this - // should still get fixed. Either by preventing writeback from defining new opaque - // types or by using this function at the end of writeback and running it as a - // fixpoint. let opaque_types = self.fcx.infcx.clone_opaque_types(); + let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries(); + let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries)); + debug_assert_eq!(prev, None); for (opaque_type_key, hidden_type) in opaque_types { let hidden_type = self.resolve(hidden_type, &hidden_type.span); let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span); diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 22d7ce79bb462..359b9da11ced6 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -6,7 +6,10 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; -use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; +use super::{ + BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin, + SubregionOrigin, +}; impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; @@ -213,4 +216,58 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); } + + type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; + fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries { + self.inner.borrow_mut().opaque_types().num_entries() + } + fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect() + } + fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .iter_duplicate_entries() + .map(|(k, h)| (k, h.ty)) + .collect() + } + fn clone_opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_types() + .opaque_types_added_since(prev_entries) + .map(|(k, h)| (k, h.ty)) + .collect() + } + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) -> Option> { + self.register_hidden_type_in_storage( + opaque_type_key, + ty::OpaqueHiddenType { span, ty: hidden_ty }, + ) + } + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) { + self.inner + .borrow_mut() + .opaque_types() + .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty }) + } + + fn reset_opaque_types(&self) { + let _ = self.take_opaque_types(); + } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 070d285b5a631..b408d76010d7b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,7 +9,7 @@ use free_regions::RegionRelations; pub use freshen::TypeFreshener; use lexical_region_resolve::LexicalRegionResolutions; pub use lexical_region_resolve::RegionResolutionError; -use opaque_types::OpaqueTypeStorage; +pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; use region_constraints::{ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound, }; diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index df7144c31da5a..220d5e9bda2d1 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -18,7 +18,7 @@ use crate::traits::{self, Obligation, PredicateObligations}; mod table; -pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable}; +pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable}; impl<'tcx> InferCtxt<'tcx> { /// This is a backwards compatibility hack to prevent breaking changes from diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 3c5bf9d722b97..46752840e1bab 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -14,6 +14,16 @@ pub struct OpaqueTypeStorage<'tcx> { duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>, } +/// The number of entries in the opaque type storage at a given point. +/// +/// Used to check that we haven't added any new opaque types after checking +/// the opaque types currently in the storage. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub struct OpaqueTypeStorageEntries { + opaque_types: usize, + duplicate_entries: usize, +} + impl<'tcx> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] pub(crate) fn remove( @@ -49,6 +59,24 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries)) } + pub fn num_entries(&self) -> OpaqueTypeStorageEntries { + OpaqueTypeStorageEntries { + opaque_types: self.opaque_types.len(), + duplicate_entries: self.duplicate_entries.len(), + } + } + + pub fn opaque_types_added_since( + &self, + prev_entries: OpaqueTypeStorageEntries, + ) -> impl Iterator, OpaqueHiddenType<'tcx>)> { + self.opaque_types + .iter() + .skip(prev_entries.opaque_types) + .map(|(k, v)| (*k, *v)) + .chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied()) + } + /// Only returns the opaque types from the lookup table. These are used /// when normalizing opaque types and have a unique key. /// diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index c44d9723f29d7..2a4b9776f68cb 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -24,10 +24,6 @@ impl<'tcx, OP> TypeVisitor> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { - t.super_visit_with(self); - } - fn visit_region(&mut self, r: ty::Region<'tcx>) { match r.kind() { // ignore bound regions, keep visiting diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 7f4789ad0d9b8..a8f45d043be97 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -15,7 +15,8 @@ use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; @@ -209,7 +210,7 @@ where VarFn: FnOnce() -> FxHashMap, OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>, { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 07fb2de8a3e0c..b2e35e2ff5181 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -419,7 +419,7 @@ impl CStore { match (&left_name_val, &right_name_val) { (Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) { cmp::Ordering::Equal => { - if l.0.tech_value != r.0.tech_value { + if !l.1.consistent(&tcx.sess.opts, Some(&r.1)) { report_diff( &l.0.prefix, &l.0.name, @@ -431,20 +431,28 @@ impl CStore { right_name_val = None; } cmp::Ordering::Greater => { - report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); + if !r.1.consistent(&tcx.sess.opts, None) { + report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); + } right_name_val = None; } cmp::Ordering::Less => { - report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); + if !l.1.consistent(&tcx.sess.opts, None) { + report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); + } left_name_val = None; } }, (Some(l), None) => { - report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); + if !l.1.consistent(&tcx.sess.opts, None) { + report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); + } left_name_val = None; } (None, Some(r)) => { - report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); + if !r.1.consistent(&tcx.sess.opts, None) { + report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); + } right_name_val = None; } (None, None) => break, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bc1423a9e3c2c..0250c777faf79 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2934,7 +2934,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { fn prepare_region_info(&mut self, value: &ty::Binder<'tcx, T>) where - T: TypeVisitable>, + T: TypeFoldable>, { struct RegionNameCollector<'tcx> { used_region_names: FxHashSet, diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 3853a804a920f..f804217459915 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -66,7 +66,7 @@ impl<'tcx> TyCtxt<'tcx> { { type Result = ControlFlow<()>; - fn visit_binder>>( + fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, ) -> Self::Result { @@ -168,7 +168,7 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); t.super_visit_with(self); self.current_index.shift_out(1); diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 9e8fbd66b708a..90a7c2e9f7879 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -39,13 +39,6 @@ pub trait SolverDelegate: Deref + Sized { term: ::Term, ) -> Option::Predicate>>>; - fn clone_opaque_types_lookup_table( - &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; - fn clone_duplicate_opaque_types( - &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; - fn make_deduplicated_outlives_constraints( &self, ) -> Vec::GenericArg>>; @@ -64,20 +57,6 @@ pub trait SolverDelegate: Deref + Sized { span: ::Span, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> ::GenericArg; - - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, - span: ::Span, - ) -> Option<::Ty>; - fn add_duplicate_opaque_type( - &self, - opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, - span: ::Span, - ); - fn add_item_bounds_for_hidden_type( &self, def_id: ::DefId, @@ -86,7 +65,6 @@ pub trait SolverDelegate: Deref + Sized { hidden_ty: ::Ty, goals: &mut Vec::Predicate>>, ); - fn reset_opaque_types(&self); fn fetch_eligible_assoc_item( &self, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 101129a231e7d..345a272895d39 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -2,21 +2,24 @@ pub(super) mod structural_traits; +use std::ops::ControlFlow; + use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::{ - self as ty, Interner, TypeFoldable, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, + self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, + TypeVisitor, TypingMode, Upcast as _, elaborate, }; use tracing::{debug, instrument}; -use super::has_only_region_constraints; use super::trait_goals::TraitGoalProvenVia; +use super::{has_only_region_constraints, inspect}; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, - MaybeCause, NoSolution, QueryResult, + MaybeCause, NoSolution, ParamEnvSource, QueryResult, }; enum AliasBoundKind { @@ -49,18 +52,6 @@ where fn trait_def_id(self, cx: I) -> I::DefId; - /// Try equating an assumption predicate against a goal's predicate. If it - /// holds, then execute the `then` callback, which should do any additional - /// work, then produce a response (typically by executing - /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). - fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, - goal: Goal, - assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution>; - /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. @@ -119,6 +110,67 @@ where alias_ty: ty::AliasTy, ) -> Vec>; + fn probe_and_consider_param_env_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe(|candidate: &Result, NoSolution>| match candidate { + Ok(candidate) => inspect::ProbeKind::TraitCandidate { + source: candidate.source, + result: Ok(candidate.result), + }, + Err(NoSolution) => inspect::ProbeKind::TraitCandidate { + source: CandidateSource::ParamEnv(ParamEnvSource::Global), + result: Err(NoSolution), + }, + }) + .enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + let source = ecx.characterize_param_env_assumption(goal.param_env, assumption)?; + Ok(Candidate { + source, + result: ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?, + }) + }) + } + + /// Try equating an assumption predicate against a goal's predicate. If it + /// holds, then execute the `then` callback, which should do any additional + /// work, then produce a response (typically by executing + /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). + fn probe_and_match_goal_against_assumption( + ecx: &mut EvalCtxt<'_, D>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, + ) -> Result, NoSolution> { + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe_trait_candidate(source).enter(|ecx| { + Self::match_assumption(ecx, goal, assumption)?; + then(ecx) + }) + } + + /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] + /// and `DefId`. + fn fast_reject_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + + /// Relate the goal and assumption. + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -500,14 +552,8 @@ where goal: Goal, candidates: &mut Vec>, ) { - for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - candidates.extend(G::probe_and_consider_implied_clause( - self, - CandidateSource::ParamEnv(i), - goal, - assumption, - [], - )); + for assumption in goal.param_env.caller_bounds().iter() { + candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption)); } } @@ -943,4 +989,88 @@ where } } } + + /// Compute whether a param-env assumption is global or non-global after normalizing it. + /// + /// This is necessary because, for example, given: + /// + /// ```ignore,rust + /// where + /// T: Trait, + /// i32: From, + /// ``` + /// + /// The `i32: From` bound is non-global before normalization, but is global after. + /// Since the old trait solver normalized param-envs eagerly, we want to emulate this + /// behavior lazily. + fn characterize_param_env_assumption( + &mut self, + param_env: I::ParamEnv, + assumption: I::Clause, + ) -> Result, NoSolution> { + // FIXME: This should be fixed, but it also requires changing the behavior + // in the old solver which is currently relied on. + if assumption.has_bound_vars() { + return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)); + } + + match assumption.visit_with(&mut FindParamInClause { ecx: self, param_env }) { + ControlFlow::Break(Err(NoSolution)) => Err(NoSolution), + ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)), + ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)), + } + } +} + +struct FindParamInClause<'a, 'b, D: SolverDelegate, I: Interner> { + ecx: &'a mut EvalCtxt<'b, D>, + param_env: I::ParamEnv, +} + +impl TypeVisitor for FindParamInClause<'_, '_, D, I> +where + D: SolverDelegate, + I: Interner, +{ + type Result = ControlFlow>; + + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + self.ecx.enter_forall(t.clone(), |ecx, v| { + v.visit_with(&mut FindParamInClause { ecx, param_env: self.param_env }) + }) + } + + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::Placeholder(_) = ty.kind() { + ControlFlow::Break(Ok(())) + } else { + ty.super_visit_with(self) + } + } + + fn visit_const(&mut self, ct: I::Const) -> Self::Result { + let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else { + return ControlFlow::Break(Err(NoSolution)); + }; + + if let ty::ConstKind::Placeholder(_) = ct.kind() { + ControlFlow::Break(Ok(())) + } else { + ct.super_visit_with(self) + } + } + + fn visit_region(&mut self, r: I::Region) -> Self::Result { + match self.ecx.eager_resolve_region(r).kind() { + ty::ReStatic | ty::ReError(_) => ControlFlow::Continue(()), + ty::ReVar(_) | ty::RePlaceholder(_) => ControlFlow::Break(Ok(())), + ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReBound(..) => { + unreachable!() + } + } + } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 5edc777262b8d..84a83d79cf046 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -36,39 +36,38 @@ where self.def_id() } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: rustc_type_ir::solve::CandidateSource, goal: Goal, - assumption: ::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + assumption: I::Clause, + ) -> Result<(), NoSolution> { if let Some(host_clause) = assumption.as_host_effect_clause() { if host_clause.def_id() == goal.predicate.def_id() && host_clause.constness().satisfies(goal.predicate.constness) { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, host_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let host_clause = assumption.as_host_effect_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } /// Register additional assumptions for aliases corresponding to `~const` item bounds. @@ -124,7 +123,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, - impl_def_id: ::DefId, + impl_def_id: I::DefId, ) -> Result, NoSolution> { let cx = ecx.cx(); @@ -178,7 +177,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, - _guar: ::ErrorGuaranteed, + _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 65b10e4f23f0d..36f68808a2c8c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -132,12 +132,14 @@ where (Certainty::Yes, NestedNormalizationGoals(goals)) } _ => { - let certainty = shallow_certainty.unify_with(goals_certainty); + let certainty = shallow_certainty.and(goals_certainty); (certainty, NestedNormalizationGoals::empty()) } }; - if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty { + if let Certainty::Maybe(cause @ MaybeCause::Overflow { keep_constraints: false, .. }) = + certainty + { // If we have overflow, it's probable that we're substituting a type // into itself infinitely and any partial substitutions in the query // response are probably not useful anyways, so just return an empty @@ -193,6 +195,7 @@ where debug!(?num_non_region_vars, "too many inference variables -> overflow"); return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow { suggest_increasing_limit: true, + keep_constraints: false, })); } } @@ -250,13 +253,7 @@ where // to the `var_values`. let opaque_types = self .delegate - .clone_opaque_types_lookup_table() - .into_iter() - .filter(|(a, _)| { - self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) - }) - .chain(self.delegate.clone_duplicate_opaque_types()) - .collect(); + .clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries); ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c13e730805505..fc5dad9a3edf5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -23,8 +23,7 @@ use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, - HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput, - QueryResult, + HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, }; pub(super) mod canonical; @@ -99,8 +98,6 @@ where current_goal_kind: CurrentGoalKind, pub(super) var_values: CanonicalVarValues, - predefined_opaques_in_body: I::PredefinedOpaques, - /// The highest universe index nameable by the caller. /// /// When we enter a new binder inside of the query we create new universes @@ -111,6 +108,10 @@ where /// if we have a coinductive cycle and because that's the only way we can return /// new placeholders to the caller. pub(super) max_input_universe: ty::UniverseIndex, + /// The opaque types from the canonical input. We only need to return opaque types + /// which have been added to the storage while evaluating this goal. + pub(super) initial_opaque_types_storage_num_entries: + ::OpaqueTypeStorageEntries, pub(super) search_graph: &'a mut SearchGraph, @@ -305,10 +306,8 @@ where // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. - predefined_opaques_in_body: delegate - .cx() - .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()), max_input_universe: ty::UniverseIndex::ROOT, + initial_opaque_types_storage_num_entries: Default::default(), variables: Default::default(), var_values: CanonicalVarValues::dummy(), current_goal_kind: CurrentGoalKind::Misc, @@ -342,25 +341,10 @@ where canonical_goal_evaluation: &mut ProofTreeBuilder, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal) -> R, ) -> R { - let (ref delegate, input, var_values) = - SolverDelegate::build_with_canonical(cx, &canonical_input); - - let mut ecx = EvalCtxt { - delegate, - variables: canonical_input.canonical.variables, - var_values, - current_goal_kind: CurrentGoalKind::from_query_input(cx, input), - predefined_opaques_in_body: input.predefined_opaques_in_body, - max_input_universe: canonical_input.canonical.max_universe, - search_graph, - nested_goals: Default::default(), - origin_span: I::Span::dummy(), - tainted: Ok(()), - inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), - }; + let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input); for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span); + let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy()); // It may be possible that two entries in the opaque type storage end up // with the same key after resolving contained inference variables. // @@ -373,13 +357,24 @@ where // the canonical input. This is more annoying to implement and may cause a // perf regression, so we do it inside of the query for now. if let Some(prev) = prev { - debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_type_storage`"); + debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`"); } } - if !ecx.nested_goals.is_empty() { - panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals); - } + let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries(); + let mut ecx = EvalCtxt { + delegate, + variables: canonical_input.canonical.variables, + var_values, + current_goal_kind: CurrentGoalKind::from_query_input(cx, input), + max_input_universe: canonical_input.canonical.max_universe, + initial_opaque_types_storage_num_entries, + search_graph, + nested_goals: Default::default(), + origin_span: I::Span::dummy(), + tainted: Ok(()), + inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), + }; let result = f(&mut ecx, input.goal); ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe); @@ -666,7 +661,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, with_resolved_vars)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } else { @@ -680,7 +675,7 @@ where Certainty::Yes => {} Certainty::Maybe(_) => { self.nested_goals.push((source, goal)); - unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } @@ -1000,6 +995,14 @@ where self.delegate.resolve_vars_if_possible(value) } + pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region { + if let ty::ReVar(vid) = r.kind() { + self.delegate.opportunistic_resolve_lt_var(vid) + } else { + r + } + } + pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { let args = self.delegate.fresh_args_for_item(def_id); for arg in args.iter() { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index 0a9e7fafaea62..ed0cedc407746 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -26,32 +26,33 @@ where I: Interner, { pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T { - let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; + let ProbeCtxt { ecx: outer, probe_kind, _result } = self; - let delegate = outer_ecx.delegate; - let max_input_universe = outer_ecx.max_input_universe; - let mut nested_ecx = EvalCtxt { + let delegate = outer.delegate; + let max_input_universe = outer.max_input_universe; + let mut nested = EvalCtxt { delegate, - variables: outer_ecx.variables, - var_values: outer_ecx.var_values, - current_goal_kind: outer_ecx.current_goal_kind, - predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body, + variables: outer.variables, + var_values: outer.var_values, + current_goal_kind: outer.current_goal_kind, max_input_universe, - search_graph: outer_ecx.search_graph, - nested_goals: outer_ecx.nested_goals.clone(), - origin_span: outer_ecx.origin_span, - tainted: outer_ecx.tainted, - inspect: outer_ecx.inspect.take_and_enter_probe(), + initial_opaque_types_storage_num_entries: outer + .initial_opaque_types_storage_num_entries, + search_graph: outer.search_graph, + nested_goals: outer.nested_goals.clone(), + origin_span: outer.origin_span, + tainted: outer.tainted, + inspect: outer.inspect.take_and_enter_probe(), }; - let r = nested_ecx.delegate.probe(|| { - let r = f(&mut nested_ecx); - nested_ecx.inspect.probe_final_state(delegate, max_input_universe); + let r = nested.delegate.probe(|| { + let r = f(&mut nested); + nested.inspect.probe_final_state(delegate, max_input_universe); r }); - if !nested_ecx.inspect.is_noop() { + if !nested.inspect.is_noop() { let probe_kind = probe_kind(&r); - nested_ecx.inspect.probe_kind(probe_kind); - outer_ecx.inspect = nested_ecx.inspect.finish_probe(); + nested.inspect.probe_kind(probe_kind); + outer.inspect = nested.inspect.finish_probe(); } r } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c9f4fc649b523..8173146e2fe24 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -253,16 +253,18 @@ where } fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse]) -> CanonicalResponse { - debug_assert!(!responses.is_empty()); - if let Certainty::Maybe(maybe_cause) = - responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { - certainty.unify_with(response.value.certainty) - }) - { - self.make_ambiguous_response_no_constraints(maybe_cause) - } else { - panic!("expected flounder response to be ambiguous") - } + debug_assert!(responses.len() > 1); + let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| { + // Pull down the certainty of `Certainty::Yes` to ambiguity when combining + // these responses, b/c we're combining more than one response and this we + // don't know which one applies. + let candidate = match response.value.certainty { + Certainty::Yes => MaybeCause::Ambiguity, + Certainty::Maybe(candidate) => candidate, + }; + maybe_cause.or(candidate) + }); + self.make_ambiguous_response_no_constraints(maybe_cause) } /// If we fail to merge responses we flounder and return overflow or ambiguity. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 400b4ce1200cb..b90e34e78101c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -106,50 +106,48 @@ where self.trait_def_id(cx) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, goal: Goal, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.item_def_id() == goal.predicate.def_id() { - let cx = ecx.cx(); - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.alias.args, projection_pred.skip_binder().projection_term.args, ) { - return Err(NoSolution); + return Ok(()); } - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq( - goal.param_env, - goal.predicate.alias, - assumption_projection_pred.projection_term, - )?; - - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); - - // Add GAT where clauses from the trait's definition - // FIXME: We don't need these, since these are the type's own WF obligations. - ecx.add_goals( - GoalSource::AliasWellFormed, - cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) - .map(|pred| goal.with(cx, pred)), - ); - - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let projection_pred = assumption.as_projection_clause().unwrap(); + + let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; + + ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + + // Add GAT where clauses from the trait's definition + // FIXME: We don't need these, since these are the type's own WF obligations. + let cx = ecx.cx(); + ecx.add_goals( + GoalSource::AliasWellFormed, + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), + ); + + Ok(()) } fn consider_additional_alias_assumptions( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d19249df387c5..e3addf8bf93fc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -17,7 +17,7 @@ use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidates use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, + NoSolution, ParamEnvSource, }; impl assembly::GoalKind for TraitPredicate @@ -125,39 +125,38 @@ where .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } - fn probe_and_match_goal_against_assumption( + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, - source: CandidateSource, goal: Goal, assumption: I::Clause, - then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, - ) -> Result, NoSolution> { + ) -> Result<(), NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( goal.predicate.trait_ref.args, trait_clause.skip_binder().trait_ref.args, ) { - return Err(NoSolution); + return Ok(()); } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) } - } else { - Err(NoSolution) } + + Err(NoSolution) + } + + fn match_assumption( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + let trait_clause = assumption.as_trait_clause().unwrap(); + + let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + + Ok(()) } fn consider_auto_trait_candidate( @@ -1253,10 +1252,9 @@ where D: SolverDelegate, I: Interner, { - #[instrument(level = "debug", skip(self, goal), ret)] + #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, - goal: Goal>, mut candidates: Vec>, ) -> Result<(CanonicalResponse, Option), NoSolution> { if let TypingMode::Coherence = self.typing_mode() { @@ -1284,21 +1282,9 @@ where // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. - let has_non_global_where_bounds = candidates.iter().any(|c| match c.source { - CandidateSource::ParamEnv(idx) => { - let where_bound = goal.param_env.caller_bounds().get(idx).unwrap(); - let ty::ClauseKind::Trait(trait_pred) = where_bound.kind().skip_binder() else { - unreachable!("expected trait-bound: {where_bound:?}"); - }; - - if trait_pred.has_bound_vars() || !trait_pred.is_global() { - return true; - } - - false - } - _ => false, - }); + let has_non_global_where_bounds = candidates + .iter() + .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal))); if has_non_global_where_bounds { let where_bounds: Vec<_> = candidates .iter() @@ -1331,13 +1317,16 @@ where // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the // remaining candidates. - let proven_via = - if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) { - TraitGoalProvenVia::ParamEnv - } else { - candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_))); - TraitGoalProvenVia::Misc - }; + let proven_via = if candidates + .iter() + .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))) + { + TraitGoalProvenVia::ParamEnv + } else { + candidates + .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); + TraitGoalProvenVia::Misc + }; let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&all_candidates) { @@ -1353,7 +1342,7 @@ where goal: Goal>, ) -> Result<(CanonicalResponse, Option), NoSolution> { let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); - self.merge_trait_candidates(goal, candidates) + self.merge_trait_candidates(candidates) } fn try_stall_coroutine_witness( diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f7f354d12e8cf..47831f2f4180d 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -722,6 +722,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) + | hir::definitions::DefPathData::OpaqueLifetime(..) | hir::definitions::DefPathData::LifetimeNs(..) | hir::definitions::DefPathData::AnonAssocTy(..) => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b95ebfbe89f24..78e1a73c78813 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -83,10 +83,77 @@ pub struct TargetModifier { pub value_name: String, } +mod target_modifier_consistency_check { + use super::*; + pub(super) fn sanitizer(l: &TargetModifier, r: Option<&TargetModifier>) -> bool { + let mut lparsed: SanitizerSet = Default::default(); + let lval = if l.value_name.is_empty() { None } else { Some(l.value_name.as_str()) }; + parse::parse_sanitizers(&mut lparsed, lval); + + let mut rparsed: SanitizerSet = Default::default(); + let rval = r.filter(|v| !v.value_name.is_empty()).map(|v| v.value_name.as_str()); + parse::parse_sanitizers(&mut rparsed, rval); + + // Some sanitizers need to be target modifiers, and some do not. + // For now, we should mark all sanitizers as target modifiers except for these: + // AddressSanitizer, LeakSanitizer + let tmod_sanitizers = SanitizerSet::MEMORY + | SanitizerSet::THREAD + | SanitizerSet::HWADDRESS + | SanitizerSet::CFI + | SanitizerSet::MEMTAG + | SanitizerSet::SHADOWCALLSTACK + | SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::SAFESTACK + | SanitizerSet::DATAFLOW; + + lparsed & tmod_sanitizers == rparsed & tmod_sanitizers + } + pub(super) fn sanitizer_cfi_normalize_integers( + opts: &Options, + l: &TargetModifier, + r: Option<&TargetModifier>, + ) -> bool { + // For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier + if opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) { + if let Some(r) = r { + return l.extend().tech_value == r.extend().tech_value; + } else { + return false; + } + } + true + } +} + impl TargetModifier { pub fn extend(&self) -> ExtendedTargetModifierInfo { self.opt.reparse(&self.value_name) } + // Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`) + // When other is None, consistency with default value is checked + pub fn consistent(&self, opts: &Options, other: Option<&TargetModifier>) -> bool { + assert!(other.is_none() || self.opt == other.unwrap().opt); + match self.opt { + OptionsTargetModifiers::UnstableOptions(unstable) => match unstable { + UnstableOptionsTargetModifiers::sanitizer => { + return target_modifier_consistency_check::sanitizer(self, other); + } + UnstableOptionsTargetModifiers::sanitizer_cfi_normalize_integers => { + return target_modifier_consistency_check::sanitizer_cfi_normalize_integers( + opts, self, other, + ); + } + _ => {} + }, + _ => {} + }; + match other { + Some(other) => self.extend().tech_value == other.extend().tech_value, + None => false, + } + } } fn tmod_push_impl( @@ -2446,13 +2513,13 @@ options! { remark_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "directory into which to write optimization remarks (if not specified, they will be \ written to standard error output)"), - sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], + sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED TARGET_MODIFIER], "use a sanitizer"), sanitizer_cfi_canonical_jump_tables: Option = (Some(true), parse_opt_bool, [TRACKED], "enable canonical jump tables (default: yes)"), sanitizer_cfi_generalize_pointers: Option = (None, parse_opt_bool, [TRACKED], "enable generalizing pointer types (default: no)"), - sanitizer_cfi_normalize_integers: Option = (None, parse_opt_bool, [TRACKED], + sanitizer_cfi_normalize_integers: Option = (None, parse_opt_bool, [TRACKED TARGET_MODIFIER], "enable normalizing integer types (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 1f45440eecfce..4a99ce09b39ab 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -890,6 +890,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::Impl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) + | DefPathData::OpaqueLifetime(_) | DefPathData::AnonAssocTy(..) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 98d78520c9838..0d25b19f3fcf3 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,10 +1,15 @@ -use crate::spec::{Target, TargetMetadata, base}; +use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); + // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see + // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM. + // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning. + base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/arm64hazardfree"]); + Target { llvm_target: "aarch64-pc-windows-msvc".into(), metadata: TargetMetadata { diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 87b8db59a78ed..3601c2cba9b55 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -104,25 +104,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect()) } - fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.0 - .inner - .borrow_mut() - .opaque_types() - .iter_lookup_table() - .map(|(k, h)| (k, h.ty)) - .collect() - } - fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - self.0 - .inner - .borrow_mut() - .opaque_types() - .iter_duplicate_entries() - .map(|(k, h)| (k, h.ty)) - .collect() - } - fn make_deduplicated_outlives_constraints( &self, ) -> Vec>> { @@ -168,30 +149,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.instantiate_canonical_var(span, cv_info, universe_map) } - fn register_hidden_type_in_storage( - &self, - opaque_type_key: ty::OpaqueTypeKey<'tcx>, - hidden_ty: Ty<'tcx>, - span: Span, - ) -> Option> { - self.0.register_hidden_type_in_storage( - opaque_type_key, - ty::OpaqueHiddenType { span, ty: hidden_ty }, - ) - } - fn add_duplicate_opaque_type( - &self, - opaque_type_key: ty::OpaqueTypeKey<'tcx>, - hidden_ty: Ty<'tcx>, - span: Span, - ) { - self.0 - .inner - .borrow_mut() - .opaque_types() - .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty }) - } - fn add_item_bounds_for_hidden_type( &self, def_id: DefId, @@ -203,10 +160,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals); } - fn reset_opaque_types(&self) { - let _ = self.take_opaque_types(); - } - fn fetch_eligible_assoc_item( &self, goal_trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 2d445dd07900a..f64cd5ffebe3d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -99,7 +99,13 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + Ok(( + _, + Certainty::Maybe(MaybeCause::Overflow { + suggest_increasing_limit, + keep_constraints: _, + }), + )) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. // We discard the inference constraints from overflowing goals, so diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 24b87000e32bc..9795655e84222 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -382,7 +382,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { if let Some(term_hack) = normalizes_to_term_hack { infcx .probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env)) - .map(|certainty| ok.value.certainty.unify_with(certainty)) + .map(|certainty| ok.value.certainty.and(certainty)) } else { Ok(ok.value.certainty) } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index a54eb80fedc25..eb34cb10c68dd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -9,7 +9,7 @@ use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_span::DUMMY_SP; use tracing::{debug, info, instrument}; @@ -127,7 +127,7 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { - fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { self.outer_index.shift_in(1); t.super_visit_with(self); self.outer_index.shift_out(1); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 31d69eef5ecf4..0c49ddff39bc2 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -7,7 +7,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions, + self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, + fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; @@ -185,7 +186,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { - fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { + fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { self.depth.shift_in(1); binder.super_visit_with(self); self.depth.shift_out(1); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 27ea4e211fefe..000cf1e1fd8b1 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -128,7 +128,7 @@ impl> TypeFoldable for Binder { } } -impl> TypeVisitable for Binder { +impl> TypeVisitable for Binder { fn visit_with>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } @@ -147,7 +147,7 @@ impl> TypeSuperFoldable for Binder { } } -impl> TypeSuperVisitable for Binder { +impl> TypeSuperVisitable for Binder { fn super_visit_with>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } @@ -292,7 +292,7 @@ impl ValidateBoundVars { impl TypeVisitor for ValidateBoundVars { type Result = ControlFlow<()>; - fn visit_binder>(&mut self, t: &Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &Binder) -> Self::Result { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 7d2654de44093..c149076211739 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; @@ -245,4 +247,32 @@ pub trait InferCtxtLike: Sized { r: ::Region, span: ::Span, ); + + type OpaqueTypeStorageEntries: Debug + Copy + Default; + fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; + fn clone_opaque_types_lookup_table( + &self, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + fn clone_duplicate_opaque_types( + &self, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + fn clone_opaque_types_added_since( + &self, + prev_entries: Self::OpaqueTypeStorageEntries, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + + fn register_hidden_type_in_storage( + &self, + opaque_type_key: ty::OpaqueTypeKey, + hidden_ty: ::Ty, + span: ::Span, + ) -> Option<::Ty>; + fn add_duplicate_opaque_type( + &self, + opaque_type_key: ty::OpaqueTypeKey, + hidden_ty: ::Ty, + span: ::Span, + ); + + fn reset_opaque_types(&self); } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 4e9b87fdf74da..2e05c23a6458c 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -147,9 +147,8 @@ pub enum CandidateSource { /// For a list of all traits with builtin impls, check out the /// `EvalCtxt::assemble_builtin_impl_candidates` method. BuiltinImpl(BuiltinImplSource), - /// An assumption from the environment. - /// - /// More precisely we've used the `n-th` assumption in the `param_env`. + /// An assumption from the environment. Stores a [`ParamEnvSource`], since we + /// prefer non-global param-env candidates in candidate assembly. /// /// ## Examples /// @@ -160,7 +159,7 @@ pub enum CandidateSource { /// (x.clone(), x) /// } /// ``` - ParamEnv(usize), + ParamEnv(ParamEnvSource), /// If the self type is an alias type, e.g. an opaque type or a projection, /// we know the bounds on that alias to hold even without knowing its concrete /// underlying type. @@ -189,6 +188,14 @@ pub enum CandidateSource { CoherenceUnknowable, } +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub enum ParamEnvSource { + /// Preferred eagerly. + NonGlobal, + // Not considered unless there are non-global param-env candidates too. + Global, +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr( feature = "nightly", @@ -266,17 +273,17 @@ impl Certainty { /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` /// in ambiguity without changing the inference state, we still want to tell the /// user that `T: Baz` results in overflow. - pub fn unify_with(self, other: Certainty) -> Certainty { + pub fn and(self, other: Certainty) -> Certainty { match (self, other) { (Certainty::Yes, Certainty::Yes) => Certainty::Yes, (Certainty::Yes, Certainty::Maybe(_)) => other, (Certainty::Maybe(_), Certainty::Yes) => self, - (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.unify_with(b)), + (Certainty::Maybe(a), Certainty::Maybe(b)) => Certainty::Maybe(a.and(b)), } } pub const fn overflow(suggest_increasing_limit: bool) -> Certainty { - Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }) + Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: false }) } } @@ -289,19 +296,58 @@ pub enum MaybeCause { /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals. Ambiguity, /// We gave up due to an overflow, most often by hitting the recursion limit. - Overflow { suggest_increasing_limit: bool }, + Overflow { suggest_increasing_limit: bool, keep_constraints: bool }, } impl MaybeCause { - fn unify_with(self, other: MaybeCause) -> MaybeCause { + fn and(self, other: MaybeCause) -> MaybeCause { match (self, other) { (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, (MaybeCause::Ambiguity, MaybeCause::Overflow { .. }) => other, (MaybeCause::Overflow { .. }, MaybeCause::Ambiguity) => self, ( - MaybeCause::Overflow { suggest_increasing_limit: a }, - MaybeCause::Overflow { suggest_increasing_limit: b }, - ) => MaybeCause::Overflow { suggest_increasing_limit: a || b }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a && limit_b, + keep_constraints: keep_a && keep_b, + }, + } + } + + pub fn or(self, other: MaybeCause) -> MaybeCause { + match (self, other) { + (MaybeCause::Ambiguity, MaybeCause::Ambiguity) => MaybeCause::Ambiguity, + + // When combining ambiguity + overflow, we can keep constraints. + ( + MaybeCause::Ambiguity, + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + ( + MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ }, + MaybeCause::Ambiguity, + ) => MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: true }, + + ( + MaybeCause::Overflow { + suggest_increasing_limit: limit_a, + keep_constraints: keep_a, + }, + MaybeCause::Overflow { + suggest_increasing_limit: limit_b, + keep_constraints: keep_b, + }, + ) => MaybeCause::Overflow { + suggest_increasing_limit: limit_a || limit_b, + keep_constraints: keep_a || keep_b, + }, } } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fbd1..8ba985d2d1931 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -342,7 +342,7 @@ struct HasRegionsBoundAt { // FIXME: Could be optimized to not walk into components with no escaping bound vars. impl TypeVisitor for HasRegionsBoundAt { type Result = ControlFlow<()>; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { self.binder.shift_in(1); t.super_visit_with(self)?; self.binder.shift_out(1); diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 2285e0e75de04..ccb84e2591122 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, TypeFlags}; +use crate::{self as ty, Interner, TypeFlags, TypeFoldable}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -94,7 +94,7 @@ pub trait TypeVisitor: Sized { #[cfg(not(feature = "nightly"))] type Result: VisitorResult; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { t.super_visit_with(self) } @@ -401,7 +401,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { impl TypeVisitor for HasTypeFlagsVisitor { type Result = ControlFlow; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { // If we're looking for the HAS_BINDER_VARS flag, check if the // binder has vars. This won't be present in the binder's bound // value, so we need to check here too. @@ -510,7 +510,7 @@ struct HasEscapingVarsVisitor { impl TypeVisitor for HasEscapingVarsVisitor { type Result = ControlFlow; - fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 46b0d832fec45..c81a5ff4d96e6 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -730,6 +730,10 @@ fn recursive_mkdir_empty() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn recursive_rmdir() { let tmpdir = tmpdir(); let d1 = tmpdir.join("d1"); @@ -749,6 +753,10 @@ fn recursive_rmdir() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn recursive_rmdir_of_symlink() { // test we do not recursively delete a symlink but only dirs. let tmpdir = tmpdir(); @@ -1533,6 +1541,10 @@ fn file_open_not_found() { } #[test] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn create_dir_all_with_junctions() { let tmpdir = tmpdir(); let target = tmpdir.join("target"); @@ -2011,6 +2023,10 @@ fn test_rename_symlink() { #[test] #[cfg(windows)] +#[cfg_attr( + all(windows, target_arch = "aarch64"), + ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" +)] fn test_rename_junction() { let tmpdir = tmpdir(); let original = tmpdir.join("original"); diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 19e62c4867c99..81b7ff50052a9 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -26,6 +26,10 @@ edition). Not all Rust editions have corresponding changes to the Rust style. For instance, Rust 2015, Rust 2018, and Rust 2021 all use the same style edition. +## Rust next style edition + +- Never break within a nullary function call `func()` or a unit literal `()`. + ## Rust 2024 style edition This style guide describes the Rust 2024 style edition. The Rust 2024 style diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 031e59d86e1da..9df5d7d18edb5 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -183,6 +183,10 @@ let f = Foo { }; ``` +## Unit literals + +Never break between the opening and closing parentheses of the `()` unit literal. + ## Tuple literals Use a single-line form where possible. Do not put spaces between the opening @@ -377,6 +381,11 @@ Do put a space between an argument, and the comma which precedes it. Prefer not to break a line in the callee expression. +For a function call with no arguments (a nullary function call like `func()`), +never break within the parentheses, and never put a space between the +parentheses. Always write a nullary function call as a single-line call, never +a multi-line call. + ### Single-line calls Do not put a space between the function name and open paren, between the open diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bbe11bf56af30..15890fff0c336 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -786,7 +786,11 @@ impl Item { // because it isn't public API. None } - _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)), + _ => Some({ + let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); + assert_eq!(s.pop(), Some('\n')); + s + }), } } else if attr.has_any_name(ALLOWED_ATTRIBUTES) { Some( diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 8db9cd593b335..da09edd7f7c03 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -20,8 +20,8 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, - GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, + GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -915,7 +915,7 @@ pub fn for_each_top_level_late_bound_region( ControlFlow::Continue(()) } } - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { self.index += 1; let res = t.super_visit_with(self); self.index -= 1; diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 1449e9af19aa5..5757e422ae21e 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -35,6 +35,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-32bit", "ignore-64bit", "ignore-aarch64", + "ignore-aarch64-pc-windows-msvc", "ignore-aarch64-unknown-linux-gnu", "ignore-aix", "ignore-android", diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs index 223c41b15bb35..430de6f736a51 100644 --- a/tests/codegen/naked-asan.rs +++ b/tests/codegen/naked-asan.rs @@ -4,6 +4,8 @@ //@ needs-sanitizer-address //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer + #![crate_type = "lib"] #![no_std] #![feature(abi_x86_interrupt)] diff --git a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs index f319306f93fd8..b19920b8e6d1c 100644 --- a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs +++ b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs @@ -20,6 +20,7 @@ // //@ revisions:ASAN ASAN-FAT-LTO //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@[ASAN] compile-flags: //@[ASAN-FAT-LTO] compile-flags: -Cprefer-dynamic=false -Clto=fat diff --git a/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs b/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs index 22577e2a3c46b..82fd290d7069a 100644 --- a/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs +++ b/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs @@ -3,6 +3,8 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer + #![crate_type = "lib"] pub fn foo() {} diff --git a/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs index a54a6d84a8073..59271b228c4ba 100644 --- a/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs +++ b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs @@ -3,6 +3,8 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-normalize-integers + #![crate_type = "lib"] pub fn foo() {} diff --git a/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs b/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs index 283b8f2610294..50042f7724a1f 100644 --- a/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs +++ b/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/dbg-location-on-cfi-blocks.rs b/tests/codegen/sanitizer/cfi/dbg-location-on-cfi-blocks.rs index df65960dfe0be..2085d121aa306 100644 --- a/tests/codegen/sanitizer/cfi/dbg-location-on-cfi-blocks.rs +++ b/tests/codegen/sanitizer/cfi/dbg-location-on-cfi-blocks.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -Cdebuginfo=1 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs index 71ccdc8ca624f..18dfe51a63309 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-checks.rs b/tests/codegen/sanitizer/cfi/emit-type-checks.rs index ebc66a015df69..2cab35f23520b 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-checks.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-checks.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs index 9bc2e42db0f61..59469c987dc76 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(cfi_encoding, extern_types)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs index 9048c6a1f1838..a74a582694f51 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(type_alias_impl_trait)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs index 2a7eca6fc1963..6cb096f9f3835 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs index 7e60aafff6802..0a27c36987512 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs index 36d2e8c9f25a2..6795860331aac 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(type_alias_impl_trait)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs index 9d611777ff0ba..0e700b39afd54 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs index a8ba8db1be3b4..0f687221d4aff 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(type_alias_impl_trait)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs index d37bb740f5505..c1c2c95723043 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs index 7d9e4d0587276..719236ea9811e 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs index 0f97c70f3f923..07a89844d3af9 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs index bdee3f47a837d..8ca445843371a 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs index 55e816178f8fc..196c4dbd7499f 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs index c1f3ca61afeb1..fab158586dcab 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(extern_types)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs index 32637b64b3ea8..dafbb770d3b81 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs index 51121b0aef1aa..cd982c3249b3b 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-normalize-integers #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs index 1cfdd23006e3a..05ec3f31bc31f 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-normalize-integers #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs index 56ab1ce4b3582..390ae0c0fd3e9 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs index 0e57ce322d127..36c96c4272c68 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/external_weak_symbols.rs b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs index 00e9b5029af8c..4e3d331f863c9 100644 --- a/tests/codegen/sanitizer/cfi/external_weak_symbols.rs +++ b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "bin"] #![feature(linkage)] diff --git a/tests/codegen/sanitizer/cfi/generalize-pointers.rs b/tests/codegen/sanitizer/cfi/generalize-pointers.rs index 57004da6f8e06..b77e9a9d37788 100644 --- a/tests/codegen/sanitizer/cfi/generalize-pointers.rs +++ b/tests/codegen/sanitizer/cfi/generalize-pointers.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/cfi/normalize-integers.rs b/tests/codegen/sanitizer/cfi/normalize-integers.rs index 770ee4e64e089..f28b7f17aa788 100644 --- a/tests/codegen/sanitizer/cfi/normalize-integers.rs +++ b/tests/codegen/sanitizer/cfi/normalize-integers.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-normalize-integers #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/dataflow-instrument-functions.rs b/tests/codegen/sanitizer/dataflow-instrument-functions.rs index a2d0d63cc1754..2145a9fe70362 100644 --- a/tests/codegen/sanitizer/dataflow-instrument-functions.rs +++ b/tests/codegen/sanitizer/dataflow-instrument-functions.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-dataflow //@ compile-flags: -Copt-level=0 -Zsanitizer=dataflow +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/memory-track-origins.rs b/tests/codegen/sanitizer/memory-track-origins.rs index 318c277e10cba..d96e4b4d59fc0 100644 --- a/tests/codegen/sanitizer/memory-track-origins.rs +++ b/tests/codegen/sanitizer/memory-track-origins.rs @@ -5,6 +5,7 @@ //@ revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO // //@ compile-flags: -Zsanitizer=memory -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@[MSAN-0] compile-flags: //@[MSAN-1] compile-flags: -Zsanitizer-memory-track-origins=1 //@[MSAN-2] compile-flags: -Zsanitizer-memory-track-origins diff --git a/tests/codegen/sanitizer/no-sanitize-inlining.rs b/tests/codegen/sanitizer/no-sanitize-inlining.rs index 4bd832d2ab195..79bd454d1d096 100644 --- a/tests/codegen/sanitizer/no-sanitize-inlining.rs +++ b/tests/codegen/sanitizer/no-sanitize-inlining.rs @@ -5,6 +5,7 @@ //@ needs-sanitizer-leak //@ revisions: ASAN LSAN //@ compile-flags: -Copt-level=3 -Zmir-opt-level=4 -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@[ASAN] compile-flags: -Zsanitizer=address //@[LSAN] compile-flags: -Zsanitizer=leak diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index 2a309f6b9c696..727f0c5891296 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-address //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/safestack-attr-check.rs b/tests/codegen/sanitizer/safestack-attr-check.rs index 050a60333afa1..9ae45828439e7 100644 --- a/tests/codegen/sanitizer/safestack-attr-check.rs +++ b/tests/codegen/sanitizer/safestack-attr-check.rs @@ -2,6 +2,7 @@ // //@ needs-sanitizer-safestack //@ compile-flags: -Zsanitizer=safestack -Copt-level=0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/sanitizer-recover.rs b/tests/codegen/sanitizer/sanitizer-recover.rs index 6b65932048184..4363e16389ef3 100644 --- a/tests/codegen/sanitizer/sanitizer-recover.rs +++ b/tests/codegen/sanitizer/sanitizer-recover.rs @@ -7,6 +7,7 @@ //@ no-prefer-dynamic // //@ compile-flags: -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@[ASAN] compile-flags: -Zsanitizer=address -Copt-level=0 //@[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0 //@[MSAN] compile-flags: -Zsanitizer=memory diff --git a/tests/debuginfo/step-into-match.rs b/tests/debuginfo/step-into-match.rs index 577e553c11985..d4b7ea201195e 100644 --- a/tests/debuginfo/step-into-match.rs +++ b/tests/debuginfo/step-into-match.rs @@ -1,6 +1,10 @@ //@ compile-flags: -g //@ ignore-android: FIXME(#10381) +// On Arm64 Windows, stepping at the end of a function on goes to the callsite, not the instruction +// after it. +//@ ignore-aarch64-pc-windows-msvc: Stepping out of functions behaves differently. + // === GDB TESTS ============================================================== // gdb-command: r diff --git a/tests/debuginfo/type-names.rs b/tests/debuginfo/type-names.rs index 4df6daf7b6ef0..3c7eab7e8d718 100644 --- a/tests/debuginfo/type-names.rs +++ b/tests/debuginfo/type-names.rs @@ -1,5 +1,7 @@ //@ ignore-lldb +//@ ignore-aarch64-pc-windows-msvc: Arm64 Windows cdb doesn't support JavaScript extensions. + // GDB changed the way that it formatted Foreign types //@ min-gdb-version: 9.2 diff --git a/tests/run-make/pointer-auth-link-with-c/test.rs b/tests/run-make/pointer-auth-link-with-c/test.rs index 1a3be80e898ba..795c6a45f8e61 100644 --- a/tests/run-make/pointer-auth-link-with-c/test.rs +++ b/tests/run-make/pointer-auth-link-with-c/test.rs @@ -1,4 +1,4 @@ -#[link(name = "test")] +#[link(name = "test", kind = "static")] extern "C" { fn foo() -> i32; } diff --git a/tests/rustdoc-json/attrs/automatically_derived.rs b/tests/rustdoc-json/attrs/automatically_derived.rs index 6c90d6386499c..4e1ab3d145e5d 100644 --- a/tests/rustdoc-json/attrs/automatically_derived.rs +++ b/tests/rustdoc-json/attrs/automatically_derived.rs @@ -9,5 +9,5 @@ impl Default for Manual { } } -//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]\n"]' +//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]' //@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]' diff --git a/tests/rustdoc-json/attrs/export_name_2021.rs b/tests/rustdoc-json/attrs/export_name_2021.rs index 4e6526419bdbf..254e9f6ef5bfd 100644 --- a/tests/rustdoc-json/attrs/export_name_2021.rs +++ b/tests/rustdoc-json/attrs/export_name_2021.rs @@ -1,6 +1,6 @@ //@ edition: 2021 #![no_std] -//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]\n"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' #[export_name = "altered"] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/export_name_2024.rs b/tests/rustdoc-json/attrs/export_name_2024.rs index f6a2a92b5bcd3..8129c109306c0 100644 --- a/tests/rustdoc-json/attrs/export_name_2024.rs +++ b/tests/rustdoc-json/attrs/export_name_2024.rs @@ -4,6 +4,6 @@ // The representation of `#[unsafe(export_name = ..)]` in rustdoc in edition 2024 // is still `#[export_name = ..]` without the `unsafe` attribute wrapper. -//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]\n"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' #[unsafe(export_name = "altered")] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/must_use.rs b/tests/rustdoc-json/attrs/must_use.rs index 20696dce7121e..64df8e5f509ff 100644 --- a/tests/rustdoc-json/attrs/must_use.rs +++ b/tests/rustdoc-json/attrs/must_use.rs @@ -1,9 +1,9 @@ #![no_std] -//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]\n"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]"]' #[must_use] pub fn example() -> impl Iterator {} -//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]\n"]' +//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]' #[must_use = "does nothing if you do not use it"] pub fn explicit_message() -> impl Iterator {} diff --git a/tests/rustdoc-json/attrs/no_mangle_2021.rs b/tests/rustdoc-json/attrs/no_mangle_2021.rs index 10a372572ae57..588be7256db5a 100644 --- a/tests/rustdoc-json/attrs/no_mangle_2021.rs +++ b/tests/rustdoc-json/attrs/no_mangle_2021.rs @@ -1,6 +1,6 @@ //@ edition: 2021 #![no_std] -//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]\n"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]' #[no_mangle] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/no_mangle_2024.rs b/tests/rustdoc-json/attrs/no_mangle_2024.rs index 8f3a14cbecbf7..0d500e20e6c50 100644 --- a/tests/rustdoc-json/attrs/no_mangle_2024.rs +++ b/tests/rustdoc-json/attrs/no_mangle_2024.rs @@ -4,6 +4,6 @@ // The representation of `#[unsafe(no_mangle)]` in rustdoc in edition 2024 // is still `#[no_mangle]` without the `unsafe` attribute wrapper. -//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]\n"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]' #[unsafe(no_mangle)] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/non_exhaustive.rs b/tests/rustdoc-json/attrs/non_exhaustive.rs index 3064b86422d11..b95f1a8171fd4 100644 --- a/tests/rustdoc-json/attrs/non_exhaustive.rs +++ b/tests/rustdoc-json/attrs/non_exhaustive.rs @@ -1,18 +1,18 @@ #![no_std] -//@ is "$.index[?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]\n"]' +//@ is "$.index[?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] pub enum MyEnum { First, } pub enum NonExhaustiveVariant { - //@ is "$.index[?(@.name=='Variant')].attrs" '["#[non_exhaustive]\n"]' + //@ is "$.index[?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] Variant(i64), } -//@ is "$.index[?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]\n"]' +//@ is "$.index[?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] pub struct MyStruct { pub x: i64, diff --git a/tests/rustdoc-json/keyword_private.rs b/tests/rustdoc-json/keyword_private.rs index 5e9a2c1016366..fea546c9fb605 100644 --- a/tests/rustdoc-json/keyword_private.rs +++ b/tests/rustdoc-json/keyword_private.rs @@ -5,7 +5,7 @@ //@ !has "$.index[?(@.name=='match')]" //@ has "$.index[?(@.name=='foo')]" -//@ is "$.index[?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]\n"]' +//@ is "$.index[?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]' //@ is "$.index[?(@.name=='foo')].docs" '"this is a test!"' #[doc(keyword = "match")] /// this is a test! @@ -13,7 +13,7 @@ pub mod foo {} //@ !has "$.index[?(@.name=='break')]" //@ has "$.index[?(@.name=='bar')]" -//@ is "$.index[?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]\n"]' +//@ is "$.index[?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]' //@ is "$.index[?(@.name=='bar')].docs" '"hello"' #[doc(keyword = "break")] /// hello diff --git a/tests/ui/asm/global-asm-isnt-really-a-mir-body.rs b/tests/ui/asm/global-asm-isnt-really-a-mir-body.rs index b7636d116ec6c..aef25d057d4ba 100644 --- a/tests/ui/asm/global-asm-isnt-really-a-mir-body.rs +++ b/tests/ui/asm/global-asm-isnt-really-a-mir-body.rs @@ -1,5 +1,7 @@ //@ revisions: emit_mir instrument cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer + // Make sure we don't try to emit MIR for it. //@[emit_mir] compile-flags: --emit=mir diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs index 141ad5bd2c482..7c0378e068be4 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs @@ -17,11 +17,11 @@ pub trait Foo<'a, 't> { impl<'a, 't> Foo<'a, 't> for &'a isize { fn no_bound<'b:'a>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match + //~^ ERROR lifetime parameters do not match the trait definition } fn has_bound<'b>(self, b: Inv<'b>) { - //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match + //~^ ERROR lifetime parameters do not match the trait definition } fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { @@ -40,7 +40,7 @@ impl<'a, 't> Foo<'a, 't> for &'a isize { } fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { - //~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait + //~^ ERROR lifetime parameters do not match the trait definition } fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 5f0347bdb4d49..207ca57af38b5 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -1,20 +1,48 @@ -error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:19:16 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:19:17 | +LL | fn no_bound<'b:'a>(self, b: Inv<'b>) { + | ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'b` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:10:17 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... LL | fn no_bound<'b>(self, b: Inv<'b>); - | ---- lifetimes in impl do not match this method in trait + | ^^ `'b` is late-bound ... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... LL | fn no_bound<'b:'a>(self, b: Inv<'b>) { - | ^^^^^^^ lifetimes do not match method in trait + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound -error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:23:17 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:23:18 + | +LL | fn has_bound<'b>(self, b: Inv<'b>) { + | ^^ | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'b` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:11:18 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +LL | fn no_bound<'b>(self, b: Inv<'b>); LL | fn has_bound<'b:'a>(self, b: Inv<'b>); - | ------- lifetimes in impl do not match this method in trait + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... ... LL | fn has_bound<'b>(self, b: Inv<'b>) { - | ^^^^ lifetimes do not match method in trait + | ^^ `'b` is late-bound error[E0308]: method not compatible with trait --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5 @@ -54,14 +82,45 @@ note: ...does not necessarily outlive the lifetime `'c` as defined here LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration - --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/regions-bound-missing-bound-in-impl.rs:42:30 + | +LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + | ^^^ ^^^ | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'_` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:13:21 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +... LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); - | ---------------- lifetimes in impl do not match this method in trait + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... +... +LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + | ^^^ `'_` is late-bound +note: `'_` differs between the trait and impl + --> $DIR/regions-bound-missing-bound-in-impl.rs:13:27 + | +LL | pub trait Foo<'a, 't> { + | --------------------- in this trait... +... +LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + | ^^ -- this lifetime bound makes `'d` early-bound + | | + | `'d` is early-bound +... +LL | impl<'a, 't> Foo<'a, 't> for &'a isize { + | -------------------------------------- in this impl... ... LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { - | ^ lifetimes do not match method in trait + | ^^^ `'_` is late-bound error[E0276]: impl has stricter requirements than trait --> $DIR/regions-bound-missing-bound-in-impl.rs:49:26 diff --git a/tests/ui/error-codes/E0195.rs b/tests/ui/error-codes/E0195.rs index a7e51dff2f3fd..66968f70bd9e0 100644 --- a/tests/ui/error-codes/E0195.rs +++ b/tests/ui/error-codes/E0195.rs @@ -1,13 +1,25 @@ trait Trait { +//~^ NOTE in this trait... +//~| NOTE in this trait... fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - //~^ NOTE lifetimes in impl do not match this associated function in trait + //~^ NOTE `'a` is early-bound + //~| NOTE this lifetime bound makes `'a` early-bound + //~| NOTE `'b` is early-bound + //~| NOTE this lifetime bound makes `'b` early-bound } struct Foo; impl Trait for Foo { - fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 - //~^ NOTE lifetimes do not match associated function in trait +//~^ NOTE in this impl... +//~| NOTE in this impl... + fn bar<'a,'b>(x: &'a str, y: &'b str) { + //~^ ERROR E0195 + //~| NOTE `'a` differs between the trait and impl + //~| NOTE `'a` is late-bound + //~| NOTE `'b` differs between the trait and impl + //~| NOTE `'b` is late-bound + //~| NOTE lifetime parameters differ in whether they are early- or late-bound } } diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr index 9767dee9aecd1..d0295b3643477 100644 --- a/tests/ui/error-codes/E0195.stderr +++ b/tests/ui/error-codes/E0195.stderr @@ -1,11 +1,42 @@ -error[E0195]: lifetime parameters or bounds on associated function `bar` do not match the trait declaration - --> $DIR/E0195.rs:9:11 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/E0195.rs:16:12 | +LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { + | ^^ ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/E0195.rs:4:12 + | +LL | trait Trait { + | ----------- in this trait... +... LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - | ---------- lifetimes in impl do not match this associated function in trait + | ^^ -- this lifetime bound makes `'a` early-bound + | | + | `'a` is early-bound +... +LL | impl Trait for Foo { + | ------------------ in this impl... +... +LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { + | ^^ `'a` is late-bound +note: `'b` differs between the trait and impl + --> $DIR/E0195.rs:4:15 + | +LL | trait Trait { + | ----------- in this trait... +... +LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + | ^^ -- this lifetime bound makes `'b` early-bound + | | + | `'b` is early-bound +... +LL | impl Trait for Foo { + | ------------------ in this impl... ... LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { - | ^^^^^^^ lifetimes do not match associated function in trait + | ^^ `'b` is late-bound error: aborting due to 1 previous error diff --git a/tests/ui/errors/auxiliary/file-debuginfo.rs b/tests/ui/errors/auxiliary/file-debuginfo.rs new file mode 100644 index 0000000000000..08113ec26bfd4 --- /dev/null +++ b/tests/ui/errors/auxiliary/file-debuginfo.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=debuginfo + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file-diag.rs b/tests/ui/errors/auxiliary/file-diag.rs new file mode 100644 index 0000000000000..f29c349f703b2 --- /dev/null +++ b/tests/ui/errors/auxiliary/file-diag.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=diagnostics + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file-macro.rs b/tests/ui/errors/auxiliary/file-macro.rs new file mode 100644 index 0000000000000..11abc0549a7b8 --- /dev/null +++ b/tests/ui/errors/auxiliary/file-macro.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=macro + +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/file.rs b/tests/ui/errors/auxiliary/file.rs new file mode 100644 index 0000000000000..63a7b3b58f0f5 --- /dev/null +++ b/tests/ui/errors/auxiliary/file.rs @@ -0,0 +1,8 @@ +#[macro_export] +macro_rules! my_file { + () => { file!() } +} + +pub fn file() -> &'static str { + file!() +} diff --git a/tests/ui/errors/auxiliary/trait-debuginfo.rs b/tests/ui/errors/auxiliary/trait-debuginfo.rs new file mode 100644 index 0000000000000..d5a0825fe6d13 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-debuginfo.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=debuginfo + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-diag.rs b/tests/ui/errors/auxiliary/trait-diag.rs new file mode 100644 index 0000000000000..e07961a276a9d --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-diag.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=diagnostics + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-macro.rs b/tests/ui/errors/auxiliary/trait-macro.rs new file mode 100644 index 0000000000000..48673d04ee16f --- /dev/null +++ b/tests/ui/errors/auxiliary/trait-macro.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped +//@ compile-flags: -Zremap-path-scope=macro + +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait.rs b/tests/ui/errors/auxiliary/trait.rs new file mode 100644 index 0000000000000..0e7e5400aac59 --- /dev/null +++ b/tests/ui/errors/auxiliary/trait.rs @@ -0,0 +1 @@ +pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr new file mode 100644 index 0000000000000..3ddff11798de3 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr new file mode 100644 index 0000000000000..85c781425b16a --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr new file mode 100644 index 0000000000000..792ea7925ad56 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-diag.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr new file mode 100644 index 0000000000000..d13333d2e4825 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-macro.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.rs b/tests/ui/errors/remap-path-prefix-diagnostics.rs new file mode 100644 index 0000000000000..fac7e937cb0b8 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.rs @@ -0,0 +1,57 @@ +// This test exercises `-Zremap-path-scope`, diagnostics printing paths and dependency. +// +// We test different combinations with/without remap in deps, with/without remap in this +// crate but always in deps and always here but never in deps. + +//@ revisions: with-diag-in-deps with-macro-in-deps with-debuginfo-in-deps +//@ revisions: only-diag-in-deps only-macro-in-deps only-debuginfo-in-deps +//@ revisions: not-diag-in-deps + +//@[with-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[not-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped + +//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo +//@[not-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics + +//@[with-diag-in-deps] aux-build:trait-diag.rs +//@[with-macro-in-deps] aux-build:trait-macro.rs +//@[with-debuginfo-in-deps] aux-build:trait-debuginfo.rs +//@[only-diag-in-deps] aux-build:trait-diag.rs +//@[only-macro-in-deps] aux-build:trait-macro.rs +//@[only-debuginfo-in-deps] aux-build:trait-debuginfo.rs +//@[not-diag-in-deps] aux-build:trait.rs + +// The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically +// as the remapped revision will not begin with $SRC_DIR_REAL, +// so we have to do it ourselves. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:COL" + +#[cfg(any(with_diag_in_deps, only_diag_in_deps))] +extern crate trait_diag as r#trait; + +#[cfg(any(with_macro_in_deps, only_macro_in_deps))] +extern crate trait_macro as r#trait; + +#[cfg(any(with_debuginfo_in_deps, only_debuginfo_in_deps))] +extern crate trait_debuginfo as r#trait; + +#[cfg(not_diag_in_deps)] +extern crate r#trait as r#trait; + +struct A; + +impl r#trait::Trait for A {} +//[with-macro-in-deps]~^ ERROR `A` doesn't implement `std::fmt::Display` +//[with-debuginfo-in-deps]~^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-diag-in-deps]~^^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-macro-in-deps]~^^^^ ERROR `A` doesn't implement `std::fmt::Display` +//[only-debuginfo-in-deps]~^^^^^ ERROR `A` doesn't implement `std::fmt::Display` + +//[with-diag-in-deps]~? ERROR `A` doesn't implement `std::fmt::Display` +//[not-diag-in-deps]~? ERROR `A` doesn't implement `std::fmt::Display` + +fn main() {} diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr new file mode 100644 index 0000000000000..85c781425b16a --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr new file mode 100644 index 0000000000000..08f7fb2c73642 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> remapped/errors/auxiliary/trait-diag.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr new file mode 100644 index 0000000000000..d13333d2e4825 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr @@ -0,0 +1,17 @@ +error[E0277]: `A` doesn't implement `std::fmt::Display` + --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL + | +LL | impl r#trait::Trait for A {} + | ^ `A` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `A` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Trait` + --> $DIR/auxiliary/trait-macro.rs:LL:COL + | +LL | pub trait Trait: std::fmt::Display {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout b/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout deleted file mode 100644 index 3bbdcbb8655b2..0000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.normal.run.stdout +++ /dev/null @@ -1 +0,0 @@ -remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stderr new file mode 100644 index 0000000000000..182e517571596 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.not-macro-in-deps.run.stderr @@ -0,0 +1,3 @@ +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "remapped/errors/remap-path-prefix-macro.rs" +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file::file() = "$DIR/auxiliary/file.rs" +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file!() = "remapped/errors/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stderr new file mode 100644 index 0000000000000..982c4ecead0a3 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-debuginfo-in-deps.run.stderr @@ -0,0 +1,3 @@ +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "$DIR/remap-path-prefix-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::file() = "$DIR/auxiliary/file-debuginfo.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file!() = "$DIR/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stderr new file mode 100644 index 0000000000000..7bea2e3c1acbb --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-diag-in-deps.run.stderr @@ -0,0 +1,3 @@ +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "$DIR/remap-path-prefix-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::file() = "$DIR/auxiliary/file-diag.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file!() = "$DIR/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stderr new file mode 100644 index 0000000000000..f74b0dd3ba310 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.only-macro-in-deps.run.stderr @@ -0,0 +1,3 @@ +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "$DIR/remap-path-prefix-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::file() = "remapped/errors/auxiliary/file-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file!() = "$DIR/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.rs b/tests/ui/errors/remap-path-prefix-macro.rs index 665156027c995..a3eaae0d42dc0 100644 --- a/tests/ui/errors/remap-path-prefix-macro.rs +++ b/tests/ui/errors/remap-path-prefix-macro.rs @@ -1,12 +1,52 @@ +// This test exercises `-Zremap-path-scope`, macros (like file!()) and dependency. +// +// We test different combinations with/without remap in deps, with/without remap in +// this crate but always in deps and always here but never in deps. + //@ run-pass //@ check-run-results -//@ revisions: normal with-macro-scope without-macro-scope -//@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ [with-macro-scope]compile-flags: -Zremap-path-scope=macro,diagnostics -//@ [without-macro-scope]compile-flags: -Zremap-path-scope=diagnostics -// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file. +//@ revisions: with-diag-in-deps with-macro-in-deps with-debuginfo-in-deps +//@ revisions: only-diag-in-deps only-macro-in-deps only-debuginfo-in-deps +//@ revisions: not-macro-in-deps + +//@[with-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped +//@[not-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped + +//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo +//@[not-macro-in-deps] compile-flags: -Zremap-path-scope=macro + +//@[with-diag-in-deps] aux-build:file-diag.rs +//@[with-macro-in-deps] aux-build:file-macro.rs +//@[with-debuginfo-in-deps] aux-build:file-debuginfo.rs +//@[only-diag-in-deps] aux-build:file-diag.rs +//@[only-macro-in-deps] aux-build:file-macro.rs +//@[only-debuginfo-in-deps] aux-build:file-debuginfo.rs +//@[not-macro-in-deps] aux-build:file.rs + +// The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically +// as the remapped revision will not begin with $SRC_DIR_REAL, +// so we have to do it ourselves. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:COL" + +#[cfg(any(with_diag_in_deps, only_diag_in_deps))] +extern crate file_diag as file; + +#[cfg(any(with_macro_in_deps, only_macro_in_deps))] +extern crate file_macro as file; + +#[cfg(any(with_debuginfo_in_deps, only_debuginfo_in_deps))] +extern crate file_debuginfo as file; + +#[cfg(not_macro_in_deps)] +extern crate file; fn main() { - println!("{}", file!()); + dbg!(file::my_file!()); + dbg!(file::file()); + dbg!(file!()); } diff --git a/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stderr new file mode 100644 index 0000000000000..982c4ecead0a3 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-debuginfo-in-deps.run.stderr @@ -0,0 +1,3 @@ +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "$DIR/remap-path-prefix-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::file() = "$DIR/auxiliary/file-debuginfo.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file!() = "$DIR/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stderr new file mode 100644 index 0000000000000..7bea2e3c1acbb --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-diag-in-deps.run.stderr @@ -0,0 +1,3 @@ +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "$DIR/remap-path-prefix-macro.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file::file() = "$DIR/auxiliary/file-diag.rs" +[$DIR/remap-path-prefix-macro.rs:LL:COL] file!() = "$DIR/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stderr b/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stderr new file mode 100644 index 0000000000000..3d528e9b0cb5c --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-macro.with-macro-in-deps.run.stderr @@ -0,0 +1,3 @@ +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file::my_file!() = "remapped/errors/remap-path-prefix-macro.rs" +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file::file() = "remapped/errors/auxiliary/file-macro.rs" +[remapped/errors/remap-path-prefix-macro.rs:LL:COL] file!() = "remapped/errors/remap-path-prefix-macro.rs" diff --git a/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout b/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout deleted file mode 100644 index 3bbdcbb8655b2..0000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.with-macro-scope.run.stdout +++ /dev/null @@ -1 +0,0 @@ -remapped/errors/remap-path-prefix-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout b/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout deleted file mode 100644 index 642823fec86a1..0000000000000 --- a/tests/ui/errors/remap-path-prefix-macro.without-macro-scope.run.stdout +++ /dev/null @@ -1 +0,0 @@ -$DIR/remap-path-prefix-macro.rs diff --git a/tests/ui/lto/issue-100772.rs b/tests/ui/lto/issue-100772.rs index 29ec5b9bf9647..293741be7db6a 100644 --- a/tests/ui/lto/issue-100772.rs +++ b/tests/ui/lto/issue-100772.rs @@ -1,6 +1,7 @@ //@ build-pass //@ needs-sanitizer-cfi //@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs index afc96d6bb5f54..37fce2788b7f0 100644 --- a/tests/ui/runtime/backtrace-debuginfo.rs +++ b/tests/ui/runtime/backtrace-debuginfo.rs @@ -42,9 +42,13 @@ macro_rules! dump_and_die { // there, even on i686-pc-windows-msvc. We do the best we can in // rust-lang/rust to test it as well, but sometimes we just gotta keep // landing PRs. + // + // aarch64-msvc is broken as its backtraces are truncated. + // See https://github.com/rust-lang/rust/issues/140489 if cfg!(any(target_os = "android", all(target_os = "linux", target_arch = "arm"), all(target_env = "msvc", target_arch = "x86"), + all(target_env = "msvc", target_arch = "aarch64"), target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")) { diff --git a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs index f4f383e008a08..0f2202e7ba00f 100644 --- a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs +++ b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu diff --git a/tests/ui/sanitizer/cfi/async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs index 351853ab1a710..41959b445286a 100644 --- a/tests/ui/sanitizer/cfi/async-closures.rs +++ b/tests/ui/sanitizer/cfi/async-closures.rs @@ -7,6 +7,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/can-reveal-opaques.rs b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs index 99c12d72eb524..35f150670a233 100644 --- a/tests/ui/sanitizer/cfi/can-reveal-opaques.rs +++ b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs @@ -1,5 +1,6 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/sanitizer/cfi/closures.rs b/tests/ui/sanitizer/cfi/closures.rs index 9f9002da674f5..d096cbd69c798 100644 --- a/tests/ui/sanitizer/cfi/closures.rs +++ b/tests/ui/sanitizer/cfi/closures.rs @@ -6,6 +6,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/complex-receiver.rs b/tests/ui/sanitizer/cfi/complex-receiver.rs index c7b45a775ca1d..c8a25983c32d6 100644 --- a/tests/ui/sanitizer/cfi/complex-receiver.rs +++ b/tests/ui/sanitizer/cfi/complex-receiver.rs @@ -8,6 +8,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs index 39a754f103637..1dde34bcdf0d4 100644 --- a/tests/ui/sanitizer/cfi/coroutine.rs +++ b/tests/ui/sanitizer/cfi/coroutine.rs @@ -7,6 +7,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/drop-in-place.rs b/tests/ui/sanitizer/cfi/drop-in-place.rs index 8ce2c43260261..17956aadc9a71 100644 --- a/tests/ui/sanitizer/cfi/drop-in-place.rs +++ b/tests/ui/sanitizer/cfi/drop-in-place.rs @@ -4,6 +4,7 @@ //@ only-linux //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Copt-level=0 -Cprefer-dynamic=off -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ run-pass struct EmptyDrop; diff --git a/tests/ui/sanitizer/cfi/drop-no-principal.rs b/tests/ui/sanitizer/cfi/drop-no-principal.rs index c1c88c8c71c73..2875f76f09b3d 100644 --- a/tests/ui/sanitizer/cfi/drop-no-principal.rs +++ b/tests/ui/sanitizer/cfi/drop-no-principal.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi // FIXME(#122848) Remove only-linux once OSX CFI binaries works //@ only-linux -//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi +//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi -C unsafe-allow-abi-mismatch=sanitizer //@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0 // FIXME(#118761) Should be run-pass once the labels on drop are compatible. // This test is being landed ahead of that to test that the compiler doesn't ICE while labeling the diff --git a/tests/ui/sanitizer/cfi/fn-ptr.rs b/tests/ui/sanitizer/cfi/fn-ptr.rs index 505b4b8e7f032..1943dcb4797df 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr.rs @@ -6,6 +6,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C opt-level=0 -C codegen-units=1 -C lto //@ [cfi] compile-flags: -C prefer-dynamic=off //@ [cfi] compile-flags: -Z sanitizer=cfi diff --git a/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs b/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs index d46002c69fda0..44cdcb250e701 100644 --- a/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs +++ b/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs @@ -4,6 +4,7 @@ //@ needs-sanitizer-cfi //@ check-pass //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer #![feature(cfg_sanitizer_cfi)] diff --git a/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs b/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs index 24c2c2c13da75..49e5e85ffeec4 100644 --- a/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs +++ b/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs @@ -4,6 +4,7 @@ //@ needs-sanitizer-cfi //@ check-pass //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-normalize-integers #![feature(cfg_sanitizer_cfi)] diff --git a/tests/ui/sanitizer/cfi/self-ref.rs b/tests/ui/sanitizer/cfi/self-ref.rs index 3b524ac661cf8..af757568b0080 100644 --- a/tests/ui/sanitizer/cfi/self-ref.rs +++ b/tests/ui/sanitizer/cfi/self-ref.rs @@ -6,6 +6,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/sized-associated-ty.rs b/tests/ui/sanitizer/cfi/sized-associated-ty.rs index f5b4e22e9d99b..a5ef199989e47 100644 --- a/tests/ui/sanitizer/cfi/sized-associated-ty.rs +++ b/tests/ui/sanitizer/cfi/sized-associated-ty.rs @@ -7,6 +7,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/supertraits.rs b/tests/ui/sanitizer/cfi/supertraits.rs index f80b316918804..e46f6431a9255 100644 --- a/tests/ui/sanitizer/cfi/supertraits.rs +++ b/tests/ui/sanitizer/cfi/supertraits.rs @@ -6,6 +6,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/cfi/transparent-has-regions.rs b/tests/ui/sanitizer/cfi/transparent-has-regions.rs index b70e1ea179121..e576bb2436d70 100644 --- a/tests/ui/sanitizer/cfi/transparent-has-regions.rs +++ b/tests/ui/sanitizer/cfi/transparent-has-regions.rs @@ -1,5 +1,6 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/sanitizer/cfi/virtual-auto.rs b/tests/ui/sanitizer/cfi/virtual-auto.rs index 6971d516a2057..6d5a4c9b06808 100644 --- a/tests/ui/sanitizer/cfi/virtual-auto.rs +++ b/tests/ui/sanitizer/cfi/virtual-auto.rs @@ -6,6 +6,7 @@ //@ [cfi] needs-sanitizer-cfi //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [kcfi] compile-flags: -Z sanitizer=kcfi diff --git a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs index 7d0c73c2841e8..b51bb0e403a67 100644 --- a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs +++ b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs @@ -3,6 +3,7 @@ // //@ needs-sanitizer-cfi //@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu diff --git a/tests/ui/sanitizer/issue-114275-cfi-const-expr-in-arry-len.rs b/tests/ui/sanitizer/issue-114275-cfi-const-expr-in-arry-len.rs index b1b7487fa2a4d..01d5edcdc9b64 100644 --- a/tests/ui/sanitizer/issue-114275-cfi-const-expr-in-arry-len.rs +++ b/tests/ui/sanitizer/issue-114275-cfi-const-expr-in-arry-len.rs @@ -3,6 +3,7 @@ // //@ build-pass //@ compile-flags: -Ccodegen-units=1 -Clto -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ needs-sanitizer-cfi #![crate_type = "lib"] diff --git a/tests/ui/sanitizer/kcfi-mangling.rs b/tests/ui/sanitizer/kcfi-mangling.rs index fde7b5451b6e2..adf03b86e702b 100644 --- a/tests/ui/sanitizer/kcfi-mangling.rs +++ b/tests/ui/sanitizer/kcfi-mangling.rs @@ -3,6 +3,7 @@ //@ needs-sanitizer-kcfi //@ no-prefer-dynamic //@ compile-flags: -C panic=abort -Zsanitizer=kcfi -C symbol-mangling-version=v0 +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer //@ build-pass trait Foo { diff --git a/tests/ui/target_modifiers/auxiliary/kcfi-normalize-ints.rs b/tests/ui/target_modifiers/auxiliary/kcfi-normalize-ints.rs new file mode 100644 index 0000000000000..f97005a14502d --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/kcfi-normalize-ints.rs @@ -0,0 +1,7 @@ +//@ no-prefer-dynamic +//@ needs-sanitizer-kcfi +//@ compile-flags: -C panic=abort -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/auxiliary/no-sanitizers.rs b/tests/ui/target_modifiers/auxiliary/no-sanitizers.rs new file mode 100644 index 0000000000000..1d47ff6826dab --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/no-sanitizers.rs @@ -0,0 +1,6 @@ +//@ no-prefer-dynamic +//@ compile-flags: -C panic=abort + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/auxiliary/safestack-and-kcfi.rs b/tests/ui/target_modifiers/auxiliary/safestack-and-kcfi.rs new file mode 100644 index 0000000000000..029744d2a1fe4 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/safestack-and-kcfi.rs @@ -0,0 +1,10 @@ +//@ no-prefer-dynamic + +//@ needs-sanitizer-kcfi +//@ needs-sanitizer-safestack + +//@ compile-flags: -C panic=abort -Zsanitizer=safestack,kcfi + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.rs b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.rs new file mode 100644 index 0000000000000..0d1ea1637c598 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.rs @@ -0,0 +1,19 @@ +// For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier. + +//@ needs-sanitizer-kcfi +//@ aux-build:kcfi-normalize-ints.rs +//@ compile-flags: -Cpanic=abort + +//@ revisions: ok wrong_flag wrong_sanitizer +//@[ok] compile-flags: -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers +//@[wrong_flag] compile-flags: -Zsanitizer=kcfi +//@[wrong_sanitizer] compile-flags: +//@[ok] check-pass + +#![feature(no_core)] +//[wrong_flag]~^ ERROR mixing `-Zsanitizer-cfi-normalize-integers` will cause an ABI mismatch in crate `sanitizer_kcfi_normalize_ints` +//[wrong_sanitizer]~^^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_kcfi_normalize_ints` +#![crate_type = "rlib"] +#![no_core] + +extern crate kcfi_normalize_ints; diff --git a/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_flag.stderr b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_flag.stderr new file mode 100644 index 0000000000000..ceb406cef0da5 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_flag.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zsanitizer-cfi-normalize-integers` will cause an ABI mismatch in crate `sanitizer_kcfi_normalize_ints` + --> $DIR/sanitizer-kcfi-normalize-ints.rs:13:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zsanitizer-cfi-normalize-integers` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zsanitizer-cfi-normalize-integers` in this crate is incompatible with `-Zsanitizer-cfi-normalize-integers=` in dependency `kcfi_normalize_ints` + = help: set `-Zsanitizer-cfi-normalize-integers=` in this crate or unset `-Zsanitizer-cfi-normalize-integers` in `kcfi_normalize_ints` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer-cfi-normalize-integers` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_sanitizer.stderr b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_sanitizer.stderr new file mode 100644 index 0000000000000..98a24fcd71693 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-kcfi-normalize-ints.wrong_sanitizer.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_kcfi_normalize_ints` + --> $DIR/sanitizer-kcfi-normalize-ints.rs:13:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zsanitizer` in this crate is incompatible with `-Zsanitizer=kcfi` in dependency `kcfi_normalize_ints` + = help: set `-Zsanitizer=kcfi` in this crate or unset `-Zsanitizer` in `kcfi_normalize_ints` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizers-good-for-inconsistency.rs b/tests/ui/target_modifiers/sanitizers-good-for-inconsistency.rs new file mode 100644 index 0000000000000..b94d9d2dfb423 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizers-good-for-inconsistency.rs @@ -0,0 +1,19 @@ +// AddressSanitizer, LeakSanitizer are good to be inconsistent (they are not a target modifiers) + +//@ revisions: wrong_address_san wrong_leak_san + +//@[wrong_address_san] needs-sanitizer-address +//@[wrong_leak_san] needs-sanitizer-leak + +//@ aux-build:no-sanitizers.rs +//@ compile-flags: -Cpanic=abort + +//@[wrong_address_san] compile-flags: -Zsanitizer=address +//@[wrong_leak_san] compile-flags: -Zsanitizer=leak +//@ check-pass + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate no_sanitizers; diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr new file mode 100644 index 0000000000000..440a91c7707f8 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` + --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zsanitizer` in this crate is incompatible with `-Zsanitizer=safestack,kcfi` in dependency `safestack_and_kcfi` + = help: set `-Zsanitizer=safestack,kcfi` in this crate or unset `-Zsanitizer` in `safestack_and_kcfi` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr new file mode 100644 index 0000000000000..6cdd7facc3781 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` + --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer=safestack` in this crate is incompatible with `-Zsanitizer=safestack,kcfi` in dependency `safestack_and_kcfi` + = help: set `-Zsanitizer=safestack,kcfi` in this crate or `-Zsanitizer=safestack` in `safestack_and_kcfi` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr new file mode 100644 index 0000000000000..ecfbcace39fe5 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` + --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer=kcfi` in this crate is incompatible with `-Zsanitizer=safestack,kcfi` in dependency `safestack_and_kcfi` + = help: set `-Zsanitizer=safestack,kcfi` in this crate or `-Zsanitizer=kcfi` in `safestack_and_kcfi` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs new file mode 100644 index 0000000000000..312f22f1609a8 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs @@ -0,0 +1,23 @@ +//@ needs-sanitizer-kcfi +//@ needs-sanitizer-safestack + +//@ aux-build:safestack-and-kcfi.rs +//@ compile-flags: -Cpanic=abort + +//@ revisions: good good_reverted missed_safestack missed_kcfi missed_both +//@[good] compile-flags: -Zsanitizer=safestack,kcfi +//@[good_reverted] compile-flags: -Zsanitizer=kcfi,safestack +//@[missed_safestack] compile-flags: -Zsanitizer=kcfi +//@[missed_kcfi] compile-flags: -Zsanitizer=safestack +//@[missed_both] compile-flags: +//@[good] check-pass +//@[good_reverted] check-pass + +#![feature(no_core)] +//[missed_safestack]~^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` +//[missed_kcfi]~^^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` +//[missed_both]~^^^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` +#![crate_type = "rlib"] +#![no_core] + +extern crate safestack_and_kcfi; diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr index e26cb22163f1e..f8a6252f991ea 100644 --- a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr +++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr @@ -10,26 +10,53 @@ LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; LL | fn foo<'a, K>(self, _: (), _: K) where { | ^^^^^^^ lifetimes do not match method in trait -error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:12 | -LL | fn foo<'a>(&self, state: &'a State) -> &'a T - | ---- lifetimes in impl do not match this method in trait -LL | where -LL | T: 'a; - | -- this bound might be missing in the impl -... LL | fn foo<'a>(&self, state: &'a State) -> &'a T { - | ^^^^ lifetimes do not match method in trait + | ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:14:12 + | +LL | trait Foo { + | ------------ in this trait... +LL | fn foo<'a>(&self, state: &'a State) -> &'a T + | ^^ `'a` is early-bound +LL | where +LL | T: 'a; + | -- this lifetime bound makes `'a` early-bound +... +LL | / impl Foo for F +LL | | where +LL | | F: Fn(&State) -> &T, + | |________________________- in this impl... +LL | { +LL | fn foo<'a>(&self, state: &'a State) -> &'a T { + | ^^ `'a` is late-bound -error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11 +error[E0195]: lifetime parameters do not match the trait definition + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:12 + | +LL | fn foo<'a: 'a>(&'a self) {} + | ^^ + | + = note: lifetime parameters differ in whether they are early- or late-bound +note: `'a` differs between the trait and impl + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:29:12 | +LL | trait Bar { + | --------- in this trait... LL | fn foo<'a>(&'a self) {} - | ---- lifetimes in impl do not match this method in trait + | ^^ `'a` is late-bound ... +LL | impl Bar for () { + | --------------- in this impl... LL | fn foo<'a: 'a>(&'a self) {} - | ^^^^^^^^ lifetimes do not match method in trait + | ^^ -- this lifetime bound makes `'a` early-bound + | | + | `'a` is early-bound error: aborting due to 3 previous errors diff --git a/tests/ui/traits/next-solver/global-param-env-after-norm.rs b/tests/ui/traits/next-solver/global-param-env-after-norm.rs new file mode 100644 index 0000000000000..0d098db67d36d --- /dev/null +++ b/tests/ui/traits/next-solver/global-param-env-after-norm.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +struct NewSolver; +struct OldSolver; + +fn foo() +where + T: Iterator, + OldSolver: Into, +{ + let x: OldSolver = OldSolver.into(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index e91a48f62aec3..f5fd9ce9864ce 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,24 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error[E0275]: overflow evaluating the requirement `::Assoc well-formed` - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - -error[E0275]: overflow evaluating the requirement `T: Trait` - --> $DIR/normalize-param-env-4.rs:32:19 - | -LL | impls_trait::(); - | ^ - | -note: required by a bound in `impls_trait` - --> $DIR/normalize-param-env-4.rs:15:19 - | -LL | fn impls_trait() {} - | ^^^^^ required by this bound in `impls_trait` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs b/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs new file mode 100644 index 0000000000000..4b20cd11b0d41 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow-plus-ambiguity-normalizes-to-response.rs @@ -0,0 +1,56 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for . +// See comment below on `fn main`. + +trait Intersect { + type Output; +} + +impl Intersect> for T +where + T: Intersect, +{ + type Output = T; +} + +impl Intersect for Cuboid { + type Output = Cuboid; +} + +fn intersect(_: &T, _: &U) -> T::Output +where + T: Intersect, +{ + todo!() +} + +struct Cuboid; +impl Cuboid { + fn method(&self) {} +} + +fn main() { + let x = vec![]; + // Here we end up trying to normalize `>>::Output` + // for the return type of the function, to constrain `y`. The impl then requires + // `Cuboid: Intersect`, which has two candidates. One that constrains + // `?0 = Vec`, which itself has the same two candidates and ends up leading + // to a recursion depth overflow. In the second impl, we constrain `?0 = Cuboid`. + // + // Floundering leads to us combining the overflow candidate and yes candidate to + // overflow. Because the response was overflow, we used to bubble it up to the + // parent normalizes-to goal, which caused us to drop its constraint that would + // guide us to normalize the associated type mentioned before. + // + // After this PR, we implement a new floundering "algebra" such that `Overflow OR Maybe` + // returns anew `Overflow { keep_constraints: true }`, which means that we don't + // need to drop constraints in the parent normalizes-to goal. This allows us to + // normalize `y` to `Cuboid`, and allows us to call the method successfully. We + // then constrain the `?0` in `let x: Vec = x` below, so that we don't have + // a left over ambiguous goal. + let y = intersect(&Cuboid, &x); + y.method(); + let x: Vec = x; +} diff --git a/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs new file mode 100644 index 0000000000000..bfaa48585ef19 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/140731 +// This tests that there's no def path conflict between the +// remapped lifetime and the lifetime present in the source. + +#![feature(impl_trait_in_assoc_type)] + +trait Trait<'a> {} + +impl<'a> Trait<'a> for u32 { + type Opq2 = impl for<'a> Trait<'a>; + //~^ ERROR: unconstrained opaque type + //~| ERROR: type `Opq2` is not a member of trait `Trait` + //~| ERROR: lifetime name `'a` shadows a lifetime name that is already in scope +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr new file mode 100644 index 0000000000000..e1544c5911b94 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/lifetime-def-path-conflict-40731.stderr @@ -0,0 +1,26 @@ +error[E0437]: type `Opq2` is not a member of trait `Trait` + --> $DIR/lifetime-def-path-conflict-40731.rs:10:5 + | +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Trait` + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/lifetime-def-path-conflict-40731.rs:10:26 + | +LL | impl<'a> Trait<'a> for u32 { + | -- first declared here +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^ lifetime `'a` already in scope + +error: unconstrained opaque type + --> $DIR/lifetime-def-path-conflict-40731.rs:10:17 + | +LL | type Opq2 = impl for<'a> Trait<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Opq2` must be used in combination with a concrete type within the same impl + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0437, E0496. +For more information about an error, try `rustc --explain E0437`. diff --git a/triagebot.toml b/triagebot.toml index 422996cb200dd..57153f1d98ab5 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1001,7 +1001,15 @@ message = "This PR changes how GCC is built. Consider updating src/bootstrap/dow message = "This PR changes a file inside `tests/crashes`. If a crash was fixed, please move into the corresponding `ui` subdir and add 'Fixes #' to the PR description to autoclose the issue upon merge." [mentions."tests/rustdoc-json"] -cc = ["@aDotInTheVoid"] +message = """ +These commits modify `test/rustdoc-json`. +rustdoc-json is a **public** (but unstable) interface. + +Please ensure that if you've changed the output: +- It's intentional. +- The `FORMAT_VERSION` in `src/librustdoc-json-types` is bumped if necessary. +""" +cc = ["@aDotInTheVoid", "@obi1kenobi"] [mentions."tests/ui/deriving/deriving-all-codegen.stdout"] message = "Changes to the code generated for builtin derived traits." @@ -1161,7 +1169,6 @@ compiler = [ "@BoxyUwU", "@compiler-errors", "@davidtwco", - "@estebank", "@fee1-dead", "@fmease", "@jieyouxu", @@ -1221,14 +1228,12 @@ incremental = [ diagnostics = [ "@compiler-errors", "@davidtwco", - "@estebank", "@oli-obk", "@chenyukang", ] parser = [ "@compiler-errors", "@davidtwco", - "@estebank", "@nnethercote", "@petrochenkov", "@spastorino", @@ -1236,7 +1241,6 @@ parser = [ lexer = [ "@nnethercote", "@petrochenkov", - "@estebank", "@chenyukang", ] arena = [ @@ -1268,7 +1272,6 @@ borrowck = [ ] ast_lowering = [ "@compiler-errors", - "@estebank", "@spastorino", ] debuginfo = [