1
Fork 0

Auto merge of #109097 - matthiaskrgr:rollup-6ydc4ri, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #108419 (Stabilize `atomic_as_ptr`)
 - #108507 (use `as_ptr` to determine the address of atomics)
 - #108607 (Don't use fd-lock on Solaris in bootstrap)
 - #108830 (Treat projections with infer as placeholder during fast reject in new solver)
 - #109055 (create `config::tests::detect_src_and_out` test for bootstrap)
 - #109058 (Document BinOp::is_checkable)
 - #109081 (simd-wide-sum test: adapt for LLVM 17 codegen change)
 - #109083 (Update books)
 - #109088 (Gracefully handle `#[target_feature]` on statics)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-14 00:30:46 +00:00
commit c54af457d0
36 changed files with 454 additions and 144 deletions

View file

@ -61,25 +61,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
// In some cases, attribute are only valid on functions, but it's the `check_attr`
// pass that check that they aren't used anywhere else, rather this module.
// In these cases, we bail from performing further checks that are only meaningful for
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
// report a delayed bug, just in case `check_attr` isn't doing its job.
let validate_fn_only_attr = |attr_sp| -> bool {
let def_kind = tcx.def_kind(did);
if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind {
true
} else {
tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions");
false
}
};
let mut inline_span = None; let mut inline_span = None;
let mut link_ordinal_span = None; let mut link_ordinal_span = None;
let mut no_sanitize_span = None; let mut no_sanitize_span = None;
for attr in attrs.iter() { for attr in attrs.iter() {
// In some cases, attribute are only valid on functions, but it's the `check_attr`
// pass that check that they aren't used anywhere else, rather this module.
// In these cases, we bail from performing further checks that are only meaningful for
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
// report a delayed bug, just in case `check_attr` isn't doing its job.
let fn_sig = || {
use DefKind::*;
let def_kind = tcx.def_kind(did);
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
Some(tcx.fn_sig(did))
} else {
tcx.sess
.delay_span_bug(attr.span, "this attribute can only be applied to functions");
None
}
};
if attr.has_name(sym::cold) { if attr.has_name(sym::cold) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
} else if attr.has_name(sym::rustc_allocator) { } else if attr.has_name(sym::rustc_allocator) {
@ -169,8 +173,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
} }
} }
} else if attr.has_name(sym::cmse_nonsecure_entry) { } else if attr.has_name(sym::cmse_nonsecure_entry) {
if validate_fn_only_attr(attr.span) if let Some(fn_sig) = fn_sig()
&& !matches!(tcx.fn_sig(did).skip_binder().abi(), abi::Abi::C { .. }) && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
{ {
struct_span_err!( struct_span_err!(
tcx.sess, tcx.sess,
@ -189,8 +193,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
} else if attr.has_name(sym::track_caller) { } else if attr.has_name(sym::track_caller) {
if !tcx.is_closure(did.to_def_id()) if !tcx.is_closure(did.to_def_id())
&& validate_fn_only_attr(attr.span) && let Some(fn_sig) = fn_sig()
&& tcx.fn_sig(did).skip_binder().abi() != abi::Abi::Rust && fn_sig.skip_binder().abi() != abi::Abi::Rust
{ {
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
.emit(); .emit();
@ -222,7 +226,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
} }
} else if attr.has_name(sym::target_feature) { } else if attr.has_name(sym::target_feature) {
if !tcx.is_closure(did.to_def_id()) if !tcx.is_closure(did.to_def_id())
&& tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal && let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
{ {
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on // The `#[target_feature]` attribute is allowed on

View file

@ -11,7 +11,7 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -99,7 +99,12 @@ impl<'tcx> InherentCollect<'tcx> {
} }
} }
if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { if let Some(simp) = simplify_type(
self.tcx,
self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else { } else {
bug!("unexpected self type: {:?}", self_ty); bug!("unexpected self type: {:?}", self_ty);
@ -159,7 +164,12 @@ impl<'tcx> InherentCollect<'tcx> {
} }
} }
if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) { if let Some(simp) = simplify_type(
self.tcx,
ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else { } else {
bug!("unexpected primitive type: {:?}", ty); bug!("unexpected primitive type: {:?}", ty);

View file

@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
use rustc_middle::middle::stability; use rustc_middle::middle::stability;
use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::AssocItem; use rustc_middle::ty::AssocItem;
use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::GenericParamDefKind;
@ -699,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} }
fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) else { let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else {
bug!("unexpected incoherent type: {:?}", self_ty) bug!("unexpected incoherent type: {:?}", self_ty)
}; };
for &impl_def_id in self.tcx.incoherent_impls(simp) { for &impl_def_id in self.tcx.incoherent_impls(simp) {

View file

@ -25,6 +25,7 @@ use rustc_infer::infer::{
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::util::supertraits; use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
@ -1257,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let target_ty = self let target_ty = self
.autoderef(sugg_span, rcvr_ty) .autoderef(sugg_span, rcvr_ty)
.find(|(rcvr_ty, _)| { .find(|(rcvr_ty, _)| {
DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer } DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }
.types_may_unify(*rcvr_ty, impl_ty) .types_may_unify(*rcvr_ty, impl_ty)
}) })
.map_or(impl_ty, |(ty, _)| ty) .map_or(impl_ty, |(ty, _)| ty)
@ -1516,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.into_iter() .into_iter()
.any(|info| self.associated_value(info.def_id, item_name).is_some()); .any(|info| self.associated_value(info.def_id, item_name).is_some());
let found_assoc = |ty: Ty<'tcx>| { let found_assoc = |ty: Ty<'tcx>| {
simplify_type(tcx, ty, TreatParams::AsInfer) simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey)
.and_then(|simp| { .and_then(|simp| {
tcx.incoherent_impls(simp) tcx.incoherent_impls(simp)
.iter() .iter()
@ -2645,9 +2646,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: Even though negative bounds are not implemented, we could maybe handle // FIXME: Even though negative bounds are not implemented, we could maybe handle
// cases where a positive bound implies a negative impl. // cases where a positive bound implies a negative impl.
(candidates, Vec::new()) (candidates, Vec::new())
} else if let Some(simp_rcvr_ty) = } else if let Some(simp_rcvr_ty) = simplify_type(
simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder) self.tcx,
{ rcvr_ty,
TreatParams::ForLookup,
TreatProjections::ForLookup,
) {
let mut potential_candidates = Vec::new(); let mut potential_candidates = Vec::new();
let mut explicitly_negative = Vec::new(); let mut explicitly_negative = Vec::new();
for candidate in candidates { for candidate in candidates {
@ -2660,8 +2664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) })
.any(|imp_did| { .any(|imp_did| {
let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
let imp_simp = let imp_simp = simplify_type(
simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder); self.tcx,
imp.self_ty(),
TreatParams::ForLookup,
TreatProjections::ForLookup,
);
imp_simp.map_or(false, |s| s == simp_rcvr_ty) imp_simp.map_or(false, |s| s == simp_rcvr_ty)
}) })
{ {

View file

@ -26,7 +26,7 @@ use rustc_middle::middle::exported_symbols::{
use rustc_middle::mir::interpret; use rustc_middle::mir::interpret;
use rustc_middle::traits::specialization_graph; use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_middle::util::common::to_readable_str; use rustc_middle::util::common::to_readable_str;
@ -1858,7 +1858,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let simplified_self_ty = fast_reject::simplify_type( let simplified_self_ty = fast_reject::simplify_type(
self.tcx, self.tcx,
trait_ref.self_ty(), trait_ref.self_ty(),
TreatParams::AsInfer, TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
); );
fx_hash_map fx_hash_map

View file

@ -1999,6 +1999,9 @@ impl BorrowKind {
} }
impl BinOp { impl BinOp {
/// The checkable operators are those whose overflow checking behavior is controlled by
/// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g.,
/// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem).
pub fn is_checkable(self) -> bool { pub fn is_checkable(self) -> bool {
use self::BinOp::*; use self::BinOp::*;
matches!(self, Add | Sub | Mul | Shl | Shr) matches!(self, Add | Sub | Mul | Shl | Shr)

View file

@ -51,15 +51,35 @@ pub enum SimplifiedType {
/// generic parameters as if they were inference variables in that case. /// generic parameters as if they were inference variables in that case.
#[derive(PartialEq, Eq, Debug, Clone, Copy)] #[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TreatParams { pub enum TreatParams {
/// Treat parameters as placeholders in the given environment. /// Treat parameters as infer vars. This is the correct mode for caching
/// an impl's type for lookup.
AsCandidateKey,
/// Treat parameters as placeholders in the given environment. This is the
/// correct mode for *lookup*, as during candidate selection.
ForLookup,
}
/// During fast-rejection, we have the choice of treating projection types
/// as either simplifyable or not, depending on whether we expect the projection
/// to be normalized/rigid.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TreatProjections {
/// In candidates, we may be able to normalize the projection
/// after instantiating the candidate and equating it with a goal.
/// ///
/// Note that this also causes us to treat projections as if they were /// We must assume that the `impl<T> Trait<T> for <T as Id>::This`
/// placeholders. This is only correct if the given projection cannot /// can apply to all self types so we don't return a simplified type
/// be normalized in the current context. Even if normalization fails, /// for `<T as Id>::This`.
/// it may still succeed later if the projection contains any inference AsCandidateKey,
/// variables. /// In the old solver we don't try to normalize projections
AsPlaceholder, /// when looking up impls and only access them by using the
AsInfer, /// current self type. This means that if the self type is
/// a projection which could later be normalized, we must not
/// treat it as rigid.
ForLookup,
/// We can treat projections in the self type as opaque as
/// we separately look up impls for the normalized self type.
NextSolverLookup,
} }
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@ -87,6 +107,7 @@ pub fn simplify_type<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
treat_params: TreatParams, treat_params: TreatParams,
treat_projections: TreatProjections,
) -> Option<SimplifiedType> { ) -> Option<SimplifiedType> {
match *ty.kind() { match *ty.kind() {
ty::Bool => Some(BoolSimplifiedType), ty::Bool => Some(BoolSimplifiedType),
@ -115,19 +136,13 @@ pub fn simplify_type<'tcx>(
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
ty::Placeholder(..) => Some(PlaceholderSimplifiedType), ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
ty::Param(_) => match treat_params { ty::Param(_) => match treat_params {
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), TreatParams::ForLookup => Some(PlaceholderSimplifiedType),
TreatParams::AsInfer => None, TreatParams::AsCandidateKey => None,
}, },
ty::Alias(..) => match treat_params { ty::Alias(..) => match treat_projections {
// When treating `ty::Param` as a placeholder, projections also TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType),
// don't unify with anything else as long as they are fully normalized. TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType),
// TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None,
// We will have to be careful with lazy normalization here.
TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
debug!("treating `{}` as a placeholder", ty);
Some(PlaceholderSimplifiedType)
}
TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
}, },
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
@ -295,8 +310,8 @@ impl DeepRejectCtxt {
// Depending on the value of `treat_obligation_params`, we either // Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables. // treat generic parameters like placeholders or like inference variables.
ty::Param(_) => match self.treat_obligation_params { ty::Param(_) => match self.treat_obligation_params {
TreatParams::AsPlaceholder => false, TreatParams::ForLookup => false,
TreatParams::AsInfer => true, TreatParams::AsCandidateKey => true,
}, },
ty::Infer(_) => true, ty::Infer(_) => true,
@ -333,8 +348,8 @@ impl DeepRejectCtxt {
let k = impl_ct.kind(); let k = impl_ct.kind();
match obligation_ct.kind() { match obligation_ct.kind() {
ty::ConstKind::Param(_) => match self.treat_obligation_params { ty::ConstKind::Param(_) => match self.treat_obligation_params {
TreatParams::AsPlaceholder => false, TreatParams::ForLookup => false,
TreatParams::AsInfer => true, TreatParams::AsCandidateKey => true,
}, },
// As we don't necessarily eagerly evaluate constants, // As we don't necessarily eagerly evaluate constants,

View file

@ -1,5 +1,5 @@
use crate::traits::specialization_graph; use crate::traits::specialization_graph;
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
use crate::ty::visit::TypeVisitableExt; use crate::ty::visit::TypeVisitableExt;
use crate::ty::{Ident, Ty, TyCtxt}; use crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE; use hir::def_id::LOCAL_CRATE;
@ -118,16 +118,32 @@ impl<'tcx> TyCtxt<'tcx> {
/// Iterate over every impl that could possibly match the self type `self_ty`. /// Iterate over every impl that could possibly match the self type `self_ty`.
/// ///
/// `trait_def_id` MUST BE the `DefId` of a trait. /// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn for_each_relevant_impl<F: FnMut(DefId)>( pub fn for_each_relevant_impl(
self, self,
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
mut f: F, f: impl FnMut(DefId),
) { ) {
let _: Option<()> = self.find_map_relevant_impl(trait_def_id, self_ty, |did| { self.for_each_relevant_impl_treating_projections(
f(did); trait_def_id,
None self_ty,
}); TreatProjections::ForLookup,
f,
)
}
pub fn for_each_relevant_impl_treating_projections(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
treat_projections: TreatProjections,
mut f: impl FnMut(DefId),
) {
let _: Option<()> =
self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
f(did);
None
});
} }
/// `trait_def_id` MUST BE the `DefId` of a trait. /// `trait_def_id` MUST BE the `DefId` of a trait.
@ -137,7 +153,12 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
) -> impl Iterator<Item = DefId> + 'tcx { ) -> impl Iterator<Item = DefId> + 'tcx {
let impls = self.trait_impls_of(trait_def_id); let impls = self.trait_impls_of(trait_def_id);
if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsInfer) { if let Some(simp) = fast_reject::simplify_type(
self,
self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) { if let Some(impls) = impls.non_blanket_impls.get(&simp) {
return impls.iter().copied(); return impls.iter().copied();
} }
@ -150,11 +171,12 @@ impl<'tcx> TyCtxt<'tcx> {
/// the first non-none value. /// the first non-none value.
/// ///
/// `trait_def_id` MUST BE the `DefId` of a trait. /// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>( pub fn find_map_relevant_impl<T>(
self, self,
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
mut f: F, treat_projections: TreatProjections,
mut f: impl FnMut(DefId) -> Option<T>,
) -> Option<T> { ) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is // FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation. // unfortunate wrt. incremental compilation.
@ -169,14 +191,13 @@ impl<'tcx> TyCtxt<'tcx> {
} }
} }
// Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using
// `TreatParams::AsInfer` while actually adding them.
//
// This way, when searching for some impl for `T: Trait`, we do not look at any impls // This way, when searching for some impl for `T: Trait`, we do not look at any impls
// whose outer level is not a parameter or projection. Especially for things like // whose outer level is not a parameter or projection. Especially for things like
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on. // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder) { if let Some(simp) =
fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections)
{
if let Some(impls) = impls.non_blanket_impls.get(&simp) { if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls { for &impl_def_id in impls {
if let result @ Some(_) = f(impl_def_id) { if let result @ Some(_) = f(impl_def_id) {
@ -237,9 +258,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
continue; continue;
} }
if let Some(simplified_self_ty) = if let Some(simplified_self_ty) = fast_reject::simplify_type(
fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsInfer) tcx,
{ impl_self_ty,
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
} else { } else {
impls.blanket_impls.push(impl_def_id); impls.blanket_impls.push(impl_def_id);

View file

@ -2,6 +2,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir; use crate::mir;
use crate::ty::fast_reject::TreatProjections;
use crate::ty::layout::IntegerExt; use crate::ty::layout::IntegerExt;
use crate::ty::{ use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@ -363,14 +364,20 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait); self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity(); let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| { let (did, constness) = self.find_map_relevant_impl(
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { drop_trait,
if validate(self, impl_did).is_ok() { ty,
return Some((*item_id, self.constness(impl_did))); // FIXME: This could also be some other mode, like "unexpected"
TreatProjections::ForLookup,
|impl_did| {
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
if validate(self, impl_did).is_ok() {
return Some((*item_id, self.constness(impl_did)));
}
} }
} None
None },
})?; )?;
Some(ty::Destructor { did, constness }) Some(ty::Destructor { did, constness })
} }

View file

@ -2215,7 +2215,7 @@ impl CheckAttrVisitor<'_> {
// `fn(TokenStream) -> TokenStream` after some substitution of generic arguments. // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
// //
// Properly checking this means pulling in additional `rustc` crates, so we don't. // Properly checking this means pulling in additional `rustc` crates, so we don't.
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };
if sig.abi != Abi::Rust { if sig.abi != Abi::Rust {
tcx.sess.emit_err(errors::ProcMacroInvalidAbi { tcx.sess.emit_err(errors::ProcMacroInvalidAbi {

View file

@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::elaborate_predicates; use rustc_infer::traits::util::elaborate_predicates;
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use std::fmt::Debug; use std::fmt::Debug;
@ -299,9 +300,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidates: &mut Vec<Candidate<'tcx>>, candidates: &mut Vec<Candidate<'tcx>>,
) { ) {
let tcx = self.tcx(); let tcx = self.tcx();
tcx.for_each_relevant_impl( tcx.for_each_relevant_impl_treating_projections(
goal.predicate.trait_def_id(tcx), goal.predicate.trait_def_id(tcx),
goal.predicate.self_ty(), goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
|impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) { |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
Ok(result) => candidates Ok(result) => candidates
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),

View file

@ -184,7 +184,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs)
.any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
{ {

View file

@ -8,7 +8,7 @@ use rustc_hir::LangItem;
use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::supertraits; use rustc_infer::traits::util::supertraits;
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -36,7 +36,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
let tcx = ecx.tcx(); let tcx = ecx.tcx();
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs) if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs)
.any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
{ {
@ -135,9 +135,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// currently instead lint patterns which can be used to // currently instead lint patterns which can be used to
// exploit this unsoundness on stable, see #93367 for // exploit this unsoundness on stable, see #93367 for
// more details. // more details.
//
// Using `TreatProjections::NextSolverLookup` is fine here because
// `instantiate_constituent_tys_for_auto_trait` returns nothing for
// projection types anyways. So it doesn't really matter what we do
// here, and this is faster.
if let Some(def_id) = ecx.tcx().find_map_relevant_impl( if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
goal.predicate.def_id(), goal.predicate.def_id(),
goal.predicate.self_ty(), goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
Some, Some,
) { ) {
debug!(?def_id, ?goal, "disqualified auto-trait implementation"); debug!(?def_id, ?goal, "disqualified auto-trait implementation");

View file

@ -75,7 +75,7 @@ pub fn overlapping_impls(
// Before doing expensive operations like entering an inference context, do // Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly // a quick check via fast_reject to tell if the impl headers could possibly
// unify. // unify.
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };
let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
let may_overlap = match (impl1_ref, impl2_ref) { let may_overlap = match (impl1_ref, impl2_ref) {

View file

@ -32,6 +32,7 @@ use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{ use rustc_middle::ty::{
@ -1799,12 +1800,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}) })
.and_then(|(trait_assoc_item, id)| { .and_then(|(trait_assoc_item, id)| {
let trait_assoc_ident = trait_assoc_item.ident(self.tcx); let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| { self.tcx.find_map_relevant_impl(
self.tcx id,
.associated_items(did) proj.projection_ty.self_ty(),
.in_definition_order() TreatProjections::ForLookup,
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) |did| {
}) self.tcx
.associated_items(did)
.in_definition_order()
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
},
)
}) })
.and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
Some( Some(
@ -2176,7 +2182,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref: &ty::PolyTraitRef<'tcx>, trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool { ) -> bool {
let get_trait_impl = |trait_def_id| { let get_trait_impl = |trait_def_id| {
self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) self.tcx.find_map_relevant_impl(
trait_def_id,
trait_ref.skip_binder().self_ty(),
TreatProjections::ForLookup,
Some,
)
}; };
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let traits_with_same_path: std::collections::BTreeSet<_> = self let traits_with_same_path: std::collections::BTreeSet<_> = self

View file

@ -9,6 +9,7 @@ use hir::LangItem;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
@ -783,6 +784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let relevant_impl = self.tcx().find_map_relevant_impl( let relevant_impl = self.tcx().find_map_relevant_impl(
self.tcx().require_lang_item(LangItem::Drop, None), self.tcx().require_lang_item(LangItem::Drop, None),
obligation.predicate.skip_binder().trait_ref.self_ty(), obligation.predicate.skip_binder().trait_ref.self_ty(),
TreatProjections::ForLookup,
Some, Some,
); );

View file

@ -2558,7 +2558,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// We can avoid creating type variables and doing the full // We can avoid creating type variables and doing the full
// substitution if we find that any of the input types, when // substitution if we find that any of the input types, when
// simplified, do not match. // simplified, do not match.
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs) iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs)
.any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp)) .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp))
} }

View file

@ -3,7 +3,7 @@ use super::OverlapError;
use crate::traits; use crate::traits;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
pub use rustc_middle::traits::specialization_graph::*; pub use rustc_middle::traits::specialization_graph::*;
@ -49,8 +49,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
/// Insert an impl into this set of children without comparing to any existing impls. /// Insert an impl into this set of children without comparing to any existing impls.
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) if let Some(st) = fast_reject::simplify_type(
{ tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
self.non_blanket_impls.entry(st).or_default().push(impl_def_id) self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
} else { } else {
@ -65,8 +69,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let vec: &mut Vec<DefId>; let vec: &mut Vec<DefId>;
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) if let Some(st) = fast_reject::simplify_type(
{ tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
) {
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
vec = self.non_blanket_impls.get_mut(&st).unwrap(); vec = self.non_blanket_impls.get_mut(&st).unwrap();
} else { } else {
@ -302,7 +310,12 @@ impl<'tcx> GraphExt<'tcx> for Graph {
let mut parent = trait_def_id; let mut parent = trait_def_id;
let mut last_lint = None; let mut last_lint = None;
let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer); let simplified = fast_reject::simplify_type(
tcx,
trait_ref.self_ty(),
TreatParams::AsCandidateKey,
TreatProjections::AsCandidateKey,
);
// Descend the specialization tree, where `parent` is the current parent node. // Descend the specialization tree, where `parent` is the current parent node.
loop { loop {

View file

@ -960,6 +960,7 @@ impl AtomicBool {
/// ```ignore (extern-declaration) /// ```ignore (extern-declaration)
/// # fn main() { /// # fn main() {
/// use std::sync::atomic::AtomicBool; /// use std::sync::atomic::AtomicBool;
///
/// extern "C" { /// extern "C" {
/// fn my_atomic_op(arg: *mut bool); /// fn my_atomic_op(arg: *mut bool);
/// } /// }
@ -971,7 +972,8 @@ impl AtomicBool {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
pub const fn as_ptr(&self) -> *mut bool { pub const fn as_ptr(&self) -> *mut bool {
self.v.get().cast() self.v.get().cast()
} }
@ -1890,7 +1892,6 @@ impl<T> AtomicPtr<T> {
/// # Examples /// # Examples
/// ///
/// ```ignore (extern-declaration) /// ```ignore (extern-declaration)
/// #![feature(atomic_mut_ptr)]
/// use std::sync::atomic::AtomicPtr; /// use std::sync::atomic::AtomicPtr;
/// ///
/// extern "C" { /// extern "C" {
@ -1906,7 +1907,8 @@ impl<T> AtomicPtr<T> {
/// } /// }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
pub const fn as_ptr(&self) -> *mut *mut T { pub const fn as_ptr(&self) -> *mut *mut T {
self.p.get() self.p.get()
} }
@ -2859,9 +2861,8 @@ macro_rules! atomic_int {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "atomic_mut_ptr", #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
reason = "recently added", #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
issue = "66893")]
pub const fn as_ptr(&self) -> *mut $int_type { pub const fn as_ptr(&self) -> *mut $int_type {
self.v.get() self.v.get()
} }

View file

@ -274,7 +274,6 @@
#![feature(utf8_chunks)] #![feature(utf8_chunks)]
// //
// Library features (core): // Library features (core):
#![feature(atomic_mut_ptr)]
#![feature(char_internals)] #![feature(char_internals)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(duration_constants)] #![feature(duration_constants)]

View file

@ -16,7 +16,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
let r = unsafe { let r = unsafe {
abi::futex_wait( abi::futex_wait(
futex.as_mut_ptr(), futex.as_ptr(),
expected, expected,
timespec.as_ref().map_or(null(), |t| t as *const abi::timespec), timespec.as_ref().map_or(null(), |t| t as *const abi::timespec),
abi::FUTEX_RELATIVE_TIMEOUT, abi::FUTEX_RELATIVE_TIMEOUT,
@ -28,12 +28,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
#[inline] #[inline]
pub fn futex_wake(futex: &AtomicU32) -> bool { pub fn futex_wake(futex: &AtomicU32) -> bool {
unsafe { abi::futex_wake(futex.as_mut_ptr(), 1) > 0 } unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 }
} }
#[inline] #[inline]
pub fn futex_wake_all(futex: &AtomicU32) { pub fn futex_wake_all(futex: &AtomicU32) {
unsafe { unsafe {
abi::futex_wake(futex.as_mut_ptr(), i32::MAX); abi::futex_wake(futex.as_ptr(), i32::MAX);
} }
} }

View file

@ -15,7 +15,6 @@
#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)] #![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)]
use crate::intrinsics;
use crate::os::raw::c_char; use crate::os::raw::c_char;
pub mod alloc; pub mod alloc;

View file

@ -47,6 +47,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage - Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage
0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed 0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed
[#77120](https://github.com/rust-lang/rust/pull/77120). [#77120](https://github.com/rust-lang/rust/pull/77120).
- File locking is now used to avoid collisions between multiple running instances of `x.py` (e.g. when using `rust-analyzer` and `x.py` at the same time). Note that Solaris and possibly other non Unix and non Windows systems don't support it [#108607](https://github.com/rust-lang/rust/pull/108607). This might possibly lead to build data corruption.
## [Version 1] - 2020-09-11 ## [Version 1] - 2020-09-11

View file

@ -32,7 +32,6 @@ test = false
[dependencies] [dependencies]
build_helper = { path = "../tools/build_helper" } build_helper = { path = "../tools/build_helper" }
cmake = "0.1.38" cmake = "0.1.38"
fd-lock = "3.0.8"
filetime = "0.2" filetime = "0.2"
getopts = "0.2.19" getopts = "0.2.19"
cc = "1.0.69" cc = "1.0.69"
@ -56,6 +55,10 @@ walkdir = "2"
# Dependencies needed by the build-metrics feature # Dependencies needed by the build-metrics feature
sysinfo = { version = "0.26.0", optional = true } sysinfo = { version = "0.26.0", optional = true }
# Solaris doesn't support flock() and thus fd-lock is not option now
[target.'cfg(not(target_os = "solaris"))'.dependencies]
fd-lock = "3.0.8"
[target.'cfg(windows)'.dependencies.winapi] [target.'cfg(windows)'.dependencies.winapi]
version = "0.3" version = "0.3"
features = [ features = [

View file

@ -7,15 +7,18 @@
use std::env; use std::env;
use bootstrap::{t, Build, Config, Subcommand, VERSION}; #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
use bootstrap::t;
use bootstrap::{Build, Config, Subcommand, VERSION};
fn main() { fn main() {
let args = env::args().skip(1).collect::<Vec<_>>(); let args = env::args().skip(1).collect::<Vec<_>>();
let config = Config::parse(&args); let config = Config::parse(&args);
let mut build_lock; #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
let _build_lock_guard; {
if cfg!(any(unix, windows)) { let mut build_lock;
let _build_lock_guard;
let path = config.out.join("lock"); let path = config.out.join("lock");
build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path))); build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
_build_lock_guard = match build_lock.try_write() { _build_lock_guard = match build_lock.try_write() {
@ -30,9 +33,9 @@ fn main() {
t!(build_lock.write()) t!(build_lock.write())
} }
}; };
} else {
println!("warning: file locking not supported for target, not locking build directory");
} }
#[cfg(any(not(any(unix, windows)), target_os = "solaris"))]
println!("warning: file locking not supported for target, not locking build directory");
// check_version warnings are not printed during setup // check_version warnings are not printed during setup
let changelog_suggestion = let changelog_suggestion =
@ -125,7 +128,7 @@ fn get_lock_owner(f: &std::path::Path) -> Option<u64> {
}) })
} }
#[cfg(not(target_os = "linux"))] #[cfg(not(any(target_os = "linux", target_os = "solaris")))]
fn get_lock_owner(_: &std::path::Path) -> Option<u64> { fn get_lock_owner(_: &std::path::Path) -> Option<u64> {
// FIXME: Implement on other OS's // FIXME: Implement on other OS's
None None

View file

@ -1,5 +1,5 @@
use super::{Config, TomlConfig}; use super::{Config, TomlConfig};
use std::path::Path; use std::{env, path::Path};
fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig { fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
|&_| toml::from_str(config).unwrap() |&_| toml::from_str(config).unwrap()
@ -33,4 +33,35 @@ fn download_ci_llvm() {
)); ));
} }
// FIXME: add test for detecting `src` and `out` #[test]
fn detect_src_and_out() {
let cfg = parse("");
// This will bring absolute form of `src/bootstrap` path
let current_dir = std::env::current_dir().unwrap();
// get `src` by moving into project root path
let expected_src = current_dir.ancestors().nth(2).unwrap();
assert_eq!(&cfg.src, expected_src);
// This should bring output path of bootstrap in absolute form
let cargo_target_dir = env::var_os("CARGO_TARGET_DIR")
.expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap");
// Move to `build` from `build/bootstrap`
let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
assert_eq!(&cfg.out, expected_out);
let args: Vec<String> = env::args().collect();
// Another test for `out` as a sanity check
//
// This will bring something similar to:
// `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
// `{config_toml_place}` can be anywhere, not just in the rust project directory.
let dep = Path::new(args.first().unwrap());
let expected_out = dep.ancestors().nth(4).unwrap();
assert_eq!(&cfg.out, expected_out);
}

@ -1 +1 @@
Subproject commit 79b53665a7c61d171fb8c5ad0b73b371f9ee6ba7 Subproject commit 1f3e4cd4fd88b5b5d45feb86a11b6d2f93e5a974

@ -1 +1 @@
Subproject commit a9afb04b47a84a6753e4dc657348c324c876102c Subproject commit 24c87f6663aed55b05d2cc286878f28f21918825

@ -1 +1 @@
Subproject commit b06dab84083390e0ee1e998f466545a8a1a76a9f Subproject commit b1b6d693cd1461e53de4132c1b183ace31cd36e5

View file

@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*;
use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def::{DefKind, Namespace, PerNS};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::Mutability; use rustc_hir::Mutability;
use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt};
use rustc_middle::{bug, ty}; use rustc_middle::{bug, ty};
use rustc_resolve::rustdoc::MalformedGenerics; use rustc_resolve::rustdoc::MalformedGenerics;
use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path}; use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path};
@ -735,7 +735,7 @@ fn trait_impls_for<'a>(
trace!("considering explicit impl for trait {:?}", trait_); trace!("considering explicit impl for trait {:?}", trait_);
// Look at each trait implementation to see if it's an impl for `did` // Look at each trait implementation to see if it's an impl for `did`
tcx.find_map_relevant_impl(trait_, ty, |impl_| { tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type. // Check if these are the same type.
let impl_type = trait_ref.skip_binder().self_ty(); let impl_type = trait_ref.skip_binder().self_ty();

View file

@ -1,4 +1,4 @@
// compile-flags: -C opt-level=3 --edition=2021 // compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
// only-x86_64 // only-x86_64
// ignore-debug: the debug assertions get in the way // ignore-debug: the debug assertions get in the way

View file

@ -14,6 +14,21 @@
#![warn(unused_attributes)] #![warn(unused_attributes)]
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
extern crate alloc;
//~^ NOTE not a function
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
use alloc::alloc::alloc;
//~^ NOTE not a function
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
extern "Rust" {}
//~^ NOTE not a function
#[target_feature = "+sse2"] #[target_feature = "+sse2"]
//~^ ERROR malformed `target_feature` attribute //~^ ERROR malformed `target_feature` attribute
#[target_feature(enable = "foo")] #[target_feature(enable = "foo")]
@ -59,6 +74,11 @@ union Qux {
f2: u16, f2: u16,
} }
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
type Uwu = ();
//~^ NOTE not a function
#[target_feature(enable = "sse2")] #[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function //~^ ERROR attribute should be applied to a function
trait Baz {} trait Baz {}
@ -69,6 +89,21 @@ trait Baz {}
#[target_feature(enable = "sse2")] #[target_feature(enable = "sse2")]
unsafe fn test() {} unsafe fn test() {}
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
static A: () = ();
//~^ NOTE not a function
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
impl Quux for u8 {}
//~^ NOTE not a function
#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
impl Foo {}
//~^ NOTE not a function
trait Quux { trait Quux {
fn foo(); fn foo();
} }

View file

@ -1,11 +1,38 @@
error: malformed `target_feature` attribute input error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:17:1 --> $DIR/invalid-attribute.rs:32:1
| |
LL | #[target_feature = "+sse2"] LL | #[target_feature = "+sse2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:34:1 --> $DIR/invalid-attribute.rs:17:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | extern crate alloc;
| ------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:22:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | use alloc::alloc::alloc;
| ------------------------ not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:27:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | extern "Rust" {}
| ---------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:49:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -14,7 +41,7 @@ LL | mod another {}
| -------------- not a function definition | -------------- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:39:1 --> $DIR/invalid-attribute.rs:54:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -23,7 +50,7 @@ LL | const FOO: usize = 7;
| --------------------- not a function definition | --------------------- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:44:1 --> $DIR/invalid-attribute.rs:59:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -32,7 +59,7 @@ LL | struct Foo;
| ----------- not a function definition | ----------- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:49:1 --> $DIR/invalid-attribute.rs:64:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -41,7 +68,7 @@ LL | enum Bar {}
| ----------- not a function definition | ----------- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:54:1 --> $DIR/invalid-attribute.rs:69:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -54,7 +81,16 @@ LL | | }
| |_- not a function definition | |_- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:62:1 --> $DIR/invalid-attribute.rs:77:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | type Uwu = ();
| -------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:82:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -63,7 +99,34 @@ LL | trait Baz {}
| ------------ not a function definition | ------------ not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:85:5 --> $DIR/invalid-attribute.rs:92:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | static A: () = ();
| ------------------ not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:97:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl Quux for u8 {}
| ------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:102:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl Foo {}
| ----------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:120:5
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -75,7 +138,7 @@ LL | | }
| |_____- not a function definition | |_____- not a function definition
error: attribute should be applied to a function definition error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:93:5 --> $DIR/invalid-attribute.rs:128:5
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -84,25 +147,25 @@ LL | || {};
| ----- not a function definition | ----- not a function definition
error: the feature named `foo` is not valid for this target error: the feature named `foo` is not valid for this target
--> $DIR/invalid-attribute.rs:19:18 --> $DIR/invalid-attribute.rs:34:18
| |
LL | #[target_feature(enable = "foo")] LL | #[target_feature(enable = "foo")]
| ^^^^^^^^^^^^^^ `foo` is not valid for this target | ^^^^^^^^^^^^^^ `foo` is not valid for this target
error: malformed `target_feature` attribute input error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:22:18 --> $DIR/invalid-attribute.rs:37:18
| |
LL | #[target_feature(bar)] LL | #[target_feature(bar)]
| ^^^ help: must be of the form: `enable = ".."` | ^^^ help: must be of the form: `enable = ".."`
error: malformed `target_feature` attribute input error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:24:18 --> $DIR/invalid-attribute.rs:39:18
| |
LL | #[target_feature(disable = "baz")] LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:28:1 --> $DIR/invalid-attribute.rs:43:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -114,13 +177,13 @@ LL | fn bar() {}
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
error: cannot use `#[inline(always)]` with `#[target_feature]` error: cannot use `#[inline(always)]` with `#[target_feature]`
--> $DIR/invalid-attribute.rs:67:1 --> $DIR/invalid-attribute.rs:87:1
| |
LL | #[inline(always)] LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:77:5 --> $DIR/invalid-attribute.rs:112:5
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -131,6 +194,6 @@ LL | fn foo() {}
= note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
error: aborting due to 15 previous errors error: aborting due to 22 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,43 @@
// check-pass
// compile-flags: -Ztrait-solver=next
// Issue 96230
use std::fmt::Debug;
trait Classic {
type Assoc;
}
trait Gat {
type Assoc<'a>;
}
struct Foo;
impl Classic for Foo {
type Assoc = ();
}
impl Gat for Foo {
type Assoc<'i> = ();
}
fn classic_debug<T: Classic>(_: T)
where
T::Assoc: Debug,
{
}
fn gat_debug<T: Gat>(_: T)
where
for<'a> T::Assoc<'a>: Debug,
{
}
fn main() {
classic_debug::<Foo>(Foo); // fine
classic_debug(Foo); // fine
gat_debug::<Foo>(Foo); // fine
gat_debug(Foo); // boom
}

View file

@ -0,0 +1,15 @@
// compile-flags: -Ztrait-solver=next
// In the new solver, we are trying to select `<?0 as Iterator>::Item: Debug`,
// which, naively can be unified with every impl of `Debug` if we're not careful.
// This test makes sure that we treat projections with inference var substs as
// placeholders during fast reject.
fn iter<T: Iterator>() -> <T as Iterator>::Item {
todo!()
}
fn main() {
println!("{:?}", iter::<_>());
//~^ ERROR type annotations needed
}

View file

@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/runaway-impl-candidate-selection.rs:13:22
|
LL | println!("{:?}", iter::<_>());
| ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.