Auto merge of #110752 - matthiaskrgr:rollup-959s77u, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #110255 (Suggest using integration tests for test crate using own proc-macro)
 - #110514 (Remove `find_map_relevant_impl`)
 - #110566 (Don't create projection ty for const projection)
 - #110637 (Group some sections of our logs in github actions)
 - #110706 (Add `intrinsics::transmute_unchecked`)
 - #110714 (Normalize types and consts in MIR opts.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-24 10:03:12 +00:00
commit 64bcb32651
38 changed files with 523 additions and 409 deletions

View file

@ -198,7 +198,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
| sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()),
sym::forget => (1, vec![param(0)], tcx.mk_unit()),
sym::transmute => (2, vec![param(0)], param(1)),
sym::transmute | sym::transmute_unchecked => (2, vec![param(0)], param(1)),
sym::prefetch_read_data
| sym::prefetch_write_data
| sym::prefetch_read_instruction

View file

@ -139,11 +139,38 @@ impl<'tcx> TyCtxt<'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
});
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
// `TreatParams::AsCandidateKey` while actually adding them.
let treat_params = match treat_projections {
TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
TreatProjections::ForLookup => TreatParams::ForLookup,
};
// 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
// `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.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
f(impl_def_id);
}
}
}
/// `trait_def_id` MUST BE the `DefId` of a trait.
@ -162,59 +189,6 @@ impl<'tcx> TyCtxt<'tcx> {
[].iter().copied()
}
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
/// the first non-none value.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn find_map_relevant_impl<T>(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
treat_projections: TreatProjections,
mut f: impl FnMut(DefId) -> Option<T>,
) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
// `TreatParams::AsCandidateKey` while actually adding them.
let treat_params = match treat_projections {
TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
TreatProjections::ForLookup => TreatParams::ForLookup,
};
// 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
// `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.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
}
None
}
/// Returns an iterator containing all impls for `trait_def_id`.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.

View file

@ -2,7 +2,6 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
use crate::ty::fast_reject::TreatProjections;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@ -359,21 +358,29 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(
drop_trait,
ty,
// 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
},
)?;
let mut dtor_candidate = None;
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
return;
};
if validate(self, impl_did).is_err() {
// Already `ErrorGuaranteed`, no need to delay a span bug here.
return;
}
if let Some((old_item_id, _)) = dtor_candidate {
self.sess
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
.span_note(self.def_span(old_item_id), "other impl here")
.delay_as_bug();
}
dtor_candidate = Some((*item_id, self.constness(impl_did)));
});
let (did, constness) = dtor_candidate?;
Some(ty::Destructor { did, constness })
}

View file

@ -323,7 +323,7 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> {
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map) -> Self {
let param_env = tcx.param_env(body.source.def_id());
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
Self {
map,
tcx,

View file

@ -120,7 +120,7 @@ impl EnumSizeOpt {
fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut alloc_cache = FxHashMap::default();
let body_did = body.source.def_id();
let param_env = tcx.param_env(body_did);
let param_env = tcx.param_env_reveal_all_normalized(body_did);
let blocks = body.basic_blocks.as_mut();
let local_decls = &mut body.local_decls;

View file

@ -221,7 +221,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Goto { target };
}
}
sym::transmute => {
sym::transmute | sym::transmute_unchecked => {
let dst_ty = destination.ty(local_decls, tcx).ty;
let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
span_bug!(

View file

@ -46,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
let param_env = tcx.param_env(def_id);
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let bbs = body.basic_blocks.as_mut();
let mut should_cleanup = false;

View file

@ -34,11 +34,23 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
self.tcx
}
#[inline]
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _: Location) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) {
constant.literal = c;
}
}
#[inline]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
*ty = self.tcx.try_normalize_erasing_regions(self.param_env, *ty).unwrap_or(*ty);
if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) {
*ty = t;
}
}
}

View file

@ -355,7 +355,7 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t
fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
debug!("build_clone_shim(def_id={:?})", def_id);
let param_env = tcx.param_env(def_id);
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
@ -836,7 +836,7 @@ fn build_call_shim<'tcx>(
pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let param_env = tcx.param_env(ctor_id);
let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
// Normalize the sig.
let sig = tcx

View file

@ -16,7 +16,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let param_env = tcx.param_env(body.source.def_id());
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
for block in body.basic_blocks_mut() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {

View file

@ -37,7 +37,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
let opts = helper.find_optimizations();
let mut storage_deads_to_insert = vec![];
let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
let param_env = tcx.param_env(body.source.def_id());
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
for opt in opts {
trace!("SUCCESS: Applying {:?}", opt);
// replace terminator with a switchInt that switches on the integer directly

View file

@ -109,7 +109,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
continue;
};
let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty));
let layout = tcx.layout_of(
tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
);
let allowed_variants = if let Ok(layout) = layout {
variant_discriminants(&layout, discriminant_ty, tcx)

View file

@ -223,3 +223,6 @@ resolve_remove_surrounding_derive =
resolve_add_as_non_derive =
add as non-Derive macro
`#[{$macro_path}]`
resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
.help = you can define integration tests in a directory named `tests`

View file

@ -508,3 +508,12 @@ pub(crate) struct RemoveSurroundingDerive {
pub(crate) struct AddAsNonDerive<'a> {
pub(crate) macro_path: &'a str,
}
#[derive(Diagnostic)]
#[diag(resolve_proc_macro_same_crate)]
pub(crate) struct ProcMacroSameCrate {
#[primary_span]
pub(crate) span: Span,
#[help]
pub(crate) is_test: bool,
}

View file

@ -1,7 +1,7 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.
use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
use crate::errors::{self, AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
use crate::Namespace::*;
use crate::{BuiltinMacroState, Determinacy};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@ -513,10 +513,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(def_id) = def_id.as_local() {
self.unused_macros.remove(&def_id);
if self.proc_macro_stubs.contains(&def_id) {
self.tcx.sess.span_err(
path.span,
"can't use a procedural macro from the same crate that defines it",
);
self.tcx.sess.emit_err(errors::ProcMacroSameCrate {
span: path.span,
is_test: self.tcx.sess.is_test_crate(),
});
}
}
}

View file

@ -1505,6 +1505,7 @@ symbols! {
transmute_generic_consts,
transmute_opts,
transmute_trait,
transmute_unchecked,
transparent,
transparent_enums,
transparent_unions,

View file

@ -645,12 +645,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// FIXME: Handling opaques here is kinda sus. Especially because we
// simplify them to PlaceholderSimplifiedType.
| ty::Alias(ty::Opaque, _) => {
if let Some(def_id) = self.tcx().find_map_relevant_impl(
let mut disqualifying_impl = None;
self.tcx().for_each_relevant_impl_treating_projections(
goal.predicate.def_id(),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
Some,
) {
|impl_def_id| {
disqualifying_impl = Some(impl_def_id);
},
);
if let Some(def_id) = disqualifying_impl {
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
// No need to actually consider the candidate here,
// since we do that in `consider_impl_candidate`.

View file

@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
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::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
});
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
let secondary_span = match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
.tcx
.opt_associated_item(proj.projection_ty.def_id)
.and_then(|trait_assoc_item| {
self.tcx
.trait_of_item(proj.projection_ty.def_id)
.map(|id| (trait_assoc_item, id))
})
.and_then(|(trait_assoc_item, id)| {
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
self.tcx.find_map_relevant_impl(
id,
proj.projection_ty.self_ty(),
TreatProjections::ForLookup,
|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) {
Some(
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(_, Some(ty)),
..
})
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Type(ty),
..
}),
) => Some((
ty.span,
with_forced_trimmed_paths!(format!(
"type mismatch resolving `{}`",
self.resolve_vars_if_possible(predicate)
.print(FmtPrinter::new_with_limit(
self.tcx,
Namespace::TypeNS,
rustc_session::Limit(5),
))
.unwrap()
.into_buffer()
)),
let secondary_span = (|| {
let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
predicate.kind().skip_binder()
else {
return None;
};
let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
let mut associated_items = vec![];
self.tcx.for_each_relevant_impl(
self.tcx.trait_of_item(proj.projection_ty.def_id)?,
proj.projection_ty.self_ty(),
|impl_def_id| {
associated_items.extend(
self.tcx
.associated_items(impl_def_id)
.in_definition_order()
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
);
},
);
let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
return None;
};
match self.tcx.hir().get_if_local(associated_item.def_id) {
Some(
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(_, Some(ty)),
..
})
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Type(ty),
..
}),
) => Some((
ty.span,
with_forced_trimmed_paths!(format!(
"type mismatch resolving `{}`",
self.resolve_vars_if_possible(predicate)
.print(FmtPrinter::new_with_limit(
self.tcx,
Namespace::TypeNS,
rustc_session::Limit(5),
))
.unwrap()
.into_buffer()
)),
_ => None,
}),
_ => None,
};
)),
_ => None,
}
})();
self.note_type_err(
&mut diag,
&obligation.cause,
@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
let get_trait_impl = |trait_def_id| {
self.tcx.find_map_relevant_impl(
let get_trait_impls = |trait_def_id| {
let mut trait_impls = vec![];
self.tcx.for_each_relevant_impl(
trait_def_id,
trait_ref.skip_binder().self_ty(),
TreatProjections::ForLookup,
Some,
)
|impl_def_id| {
trait_impls.push(impl_def_id);
},
);
trait_impls
};
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let traits_with_same_path: std::collections::BTreeSet<_> = self
.tcx
@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.collect();
let mut suggested = false;
for trait_with_same_path in traits_with_same_path {
if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) {
let impl_span = self.tcx.def_span(impl_def_id);
err.span_help(impl_span, "trait impl with same name found");
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
let crate_msg = format!(
"perhaps two different versions of crate `{}` are being used?",
trait_crate
);
err.note(&crate_msg);
suggested = true;
let trait_impls = get_trait_impls(trait_with_same_path);
if trait_impls.is_empty() {
continue;
}
let impl_spans: Vec<_> =
trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
err.span_help(
impl_spans,
format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
);
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
let crate_msg = format!(
"perhaps two different versions of crate `{}` are being used?",
trait_crate
);
err.note(&crate_msg);
suggested = true;
}
suggested
}

View file

@ -1272,14 +1272,29 @@ fn project<'cx, 'tcx>(
ProjectionCandidateSet::Single(candidate) => {
Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
}
ProjectionCandidateSet::None => Ok(Projected::NoProgress(
// FIXME(associated_const_generics): this may need to change in the future?
// need to investigate whether or not this is fine.
selcx
.tcx()
.mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
)),
ProjectionCandidateSet::None => {
let tcx = selcx.tcx();
let term = match tcx.def_kind(obligation.predicate.def_id) {
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => tcx
.mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
DefKind::AssocConst => tcx
.mk_const(
ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(
obligation.predicate.def_id,
obligation.predicate.substs,
)),
tcx.type_of(obligation.predicate.def_id)
.subst(tcx, obligation.predicate.substs),
)
.into(),
kind => {
bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id))
}
};
Ok(Projected::NoProgress(term))
}
// Error occurred while trying to processing impls.
ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)),
// Inherent ambiguity that prevents us from even enumerating the

View file

@ -11,7 +11,7 @@ use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use crate::traits;
@ -875,12 +875,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::Adt(..) => {
// Find a custom `impl Drop` impl, if it exists
let relevant_impl = self.tcx().find_map_relevant_impl(
let mut relevant_impl = None;
self.tcx().for_each_relevant_impl(
self.tcx().require_lang_item(LangItem::Drop, None),
obligation.predicate.skip_binder().trait_ref.self_ty(),
TreatProjections::ForLookup,
Some,
|impl_def_id| {
if let Some(old_impl_def_id) = relevant_impl {
self.tcx()
.sess
.struct_span_err(
self.tcx().def_span(impl_def_id),
"multiple drop impls found",
)
.span_note(self.tcx().def_span(old_impl_def_id), "other impl here")
.delay_as_bug();
}
relevant_impl = Some(impl_def_id);
},
);
if let Some(impl_def_id) = relevant_impl {

View file

@ -3,8 +3,9 @@
use crate::num::NonZeroUsize;
use crate::{
fmt,
intrinsics::transmute_unchecked,
iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
mem::{self, MaybeUninit},
mem::MaybeUninit,
ops::{IndexRange, Range},
ptr,
};
@ -63,18 +64,11 @@ impl<T, const N: usize> IntoIterator for [T; N] {
// an array of `T`.
//
// With that, this initialization satisfies the invariants.
// FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
// works with const generics:
// `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
//
// Until then, we can use `mem::transmute_copy` to create a bitwise copy
// as a different type, then forget `array` so that it is not dropped.
unsafe {
let iter = IntoIter { data: mem::transmute_copy(&self), alive: IndexRange::zero_to(N) };
mem::forget(self);
iter
}
// FIXME: If normal `transmute` ever gets smart enough to allow this
// directly, use it instead of `transmute_unchecked`.
let data: [MaybeUninit<T>; N] = unsafe { transmute_unchecked(self) };
IntoIter { data, alive: IndexRange::zero_to(N) }
}
}

View file

@ -1376,6 +1376,20 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn transmute<Src, Dst>(src: Src) -> Dst;
/// Like [`transmute`], but even less checked at compile-time: rather than
/// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's
/// **Undefined Behaviour** at runtime.
///
/// Prefer normal `transmute` where possible, for the extra checking, since
/// both do exactly the same thing at runtime, if they both compile.
///
/// This is not expected to ever be exposed directly to users, rather it
/// may eventually be exposed through some more-constrained API.
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
#[rustc_nounwind]
pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
/// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
/// implements `Copy`.
@ -2798,3 +2812,11 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
write_bytes(dst, val, count)
}
}
/// Polyfill for bootstrap
#[cfg(bootstrap)]
pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
use crate::mem::*;
// SAFETY: It's a transmute -- the caller promised it's fine.
unsafe { transmute_copy(&ManuallyDrop::new(src)) }
}

View file

@ -945,14 +945,10 @@ impl<T> MaybeUninit<T> {
// * `MaybeUninit<T>` and T are guaranteed to have the same layout
// * `MaybeUninit` does not drop, so there are no double-frees
// And thus the conversion is safe
let ret = unsafe {
unsafe {
intrinsics::assert_inhabited::<[T; N]>();
(&array as *const _ as *const [T; N]).read()
};
// FIXME: required to avoid `~const Destruct` bound
super::forget(array);
ret
intrinsics::transmute_unchecked(array)
}
}
/// Assuming all the elements are initialized, get a slice to them.

View file

@ -722,11 +722,14 @@ class RustBuild(object):
def build_bootstrap(self, color, verbose_count):
"""Build bootstrap"""
print("Building bootstrap")
env = os.environ.copy()
if "GITHUB_ACTIONS" in env:
print("::group::Building bootstrap")
else:
print("Building bootstrap")
build_dir = os.path.join(self.build_dir, "bootstrap")
if self.clean and os.path.exists(build_dir):
shutil.rmtree(build_dir)
env = os.environ.copy()
# `CARGO_BUILD_TARGET` breaks bootstrap build.
# See also: <https://github.com/rust-lang/rust/issues/70208>.
if "CARGO_BUILD_TARGET" in env:
@ -798,6 +801,9 @@ class RustBuild(object):
# Run this from the source directory so cargo finds .cargo/config
run(args, env=env, verbose=self.verbose, cwd=self.rust_root)
if "GITHUB_ACTIONS" in env:
print("::endgroup::")
def build_triple(self):
"""Build triple as in LLVM

View file

@ -105,15 +105,7 @@ impl Step for Std {
cargo.arg("--lib");
}
let msg = if compiler.host == target {
format!("Checking stage{} library artifacts ({target})", builder.top_stage)
} else {
format!(
"Checking stage{} library artifacts ({} -> {})",
builder.top_stage, &compiler.host, target
)
};
builder.info(&msg);
let _guard = builder.msg_check("library artifacts", target);
run_cargo(
builder,
cargo,
@ -167,18 +159,7 @@ impl Step for Std {
cargo.arg("-p").arg(krate.name);
}
let msg = if compiler.host == target {
format!(
"Checking stage{} library test/bench/example targets ({target})",
builder.top_stage
)
} else {
format!(
"Checking stage{} library test/bench/example targets ({} -> {})",
builder.top_stage, &compiler.host, target
)
};
builder.info(&msg);
let _guard = builder.msg_check("library test/bench/example targets", target);
run_cargo(
builder,
cargo,
@ -252,15 +233,7 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate.name);
}
let msg = if compiler.host == target {
format!("Checking stage{} compiler artifacts ({target})", builder.top_stage)
} else {
format!(
"Checking stage{} compiler artifacts ({} -> {})",
builder.top_stage, &compiler.host, target
)
};
builder.info(&msg);
let _guard = builder.msg_check("compiler artifacts", target);
run_cargo(
builder,
cargo,
@ -317,15 +290,7 @@ impl Step for CodegenBackend {
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
let msg = if compiler.host == target {
format!("Checking stage{} {} artifacts ({target})", builder.top_stage, backend)
} else {
format!(
"Checking stage{} {} library ({} -> {})",
builder.top_stage, backend, &compiler.host.triple, target.triple
)
};
builder.info(&msg);
let _guard = builder.msg_check(&backend, target);
run_cargo(
builder,
@ -385,15 +350,7 @@ impl Step for RustAnalyzer {
cargo.arg("--benches");
}
let msg = if compiler.host == target {
format!("Checking stage{} {} artifacts ({target})", compiler.stage, "rust-analyzer")
} else {
format!(
"Checking stage{} {} artifacts ({} -> {})",
compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
)
};
builder.info(&msg);
let _guard = builder.msg_check("rust-analyzer artifacts", target);
run_cargo(
builder,
cargo,
@ -460,18 +417,7 @@ macro_rules! tool_check_step {
// NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
// See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
cargo.rustflag("-Zunstable-options");
let msg = if compiler.host == target {
format!("Checking stage{} {} artifacts ({target})", builder.top_stage, stringify!($name).to_lowercase())
} else {
format!(
"Checking stage{} {} artifacts ({} -> {})",
builder.top_stage,
stringify!($name).to_lowercase(),
&compiler.host.triple,
target.triple
)
};
builder.info(&msg);
let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target);
run_cargo(
builder,
cargo,

View file

@ -143,23 +143,13 @@ impl Step for Std {
cargo.arg("-p").arg(krate);
}
let msg = if compiler.host == target {
format!(
"Building{} stage{} library artifacts ({}) ",
crate_description(&self.crates),
compiler.stage,
compiler.host
)
} else {
format!(
"Building{} stage{} library artifacts ({} -> {})",
crate_description(&self.crates),
compiler.stage,
compiler.host,
target,
)
};
builder.info(&msg);
let _guard = builder.msg(
Kind::Build,
compiler.stage,
format_args!("library artifacts{}", crate_description(&self.crates)),
compiler.host,
target,
);
run_cargo(
builder,
cargo,
@ -790,24 +780,13 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate);
}
let msg = if compiler.host == target {
format!(
"Building{} compiler artifacts (stage{} -> stage{})",
crate_description(&self.crates),
compiler.stage,
compiler.stage + 1
)
} else {
format!(
"Building{} compiler artifacts (stage{}:{} -> stage{}:{})",
crate_description(&self.crates),
compiler.stage,
compiler.host,
compiler.stage + 1,
target,
)
};
builder.info(&msg);
let _guard = builder.msg_sysroot_tool(
Kind::Build,
compiler.stage,
format_args!("compiler artifacts{}", crate_description(&self.crates)),
compiler.host,
target,
);
run_cargo(
builder,
cargo,
@ -1114,15 +1093,7 @@ impl Step for CodegenBackend {
let tmp_stamp = out_dir.join(".tmp.stamp");
let msg = if compiler.host == target {
format!("Building stage{} codegen backend {}", compiler.stage, backend)
} else {
format!(
"Building stage{} codegen backend {} ({} -> {})",
compiler.stage, backend, compiler.host, target
)
};
builder.info(&msg);
let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
if builder.config.dry_run() {
return;

View file

@ -12,7 +12,7 @@ use crate::util::t;
use crate::dist;
use crate::tarball::GeneratedTarball;
use crate::Compiler;
use crate::{Compiler, Kind};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::{Config, TargetSelection};
@ -52,7 +52,7 @@ fn install_sh(
host: Option<TargetSelection>,
tarball: &GeneratedTarball,
) {
builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
let _guard = builder.msg(Kind::Install, stage, package, host, host);
let prefix = default_path(&builder.config.prefix, "/usr/local");
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));

View file

@ -19,13 +19,14 @@
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::env;
use std::fmt::Display;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
use build_helper::ci::CiEnv;
use build_helper::ci::{gha, CiEnv};
use channel::GitInfo;
use config::{DryRun, Target};
use filetime::FileTime;
@ -993,6 +994,85 @@ impl Build {
}
}
fn msg_check(
&self,
what: impl Display,
target: impl Into<Option<TargetSelection>>,
) -> Option<gha::Group> {
self.msg(Kind::Check, self.config.stage, what, self.config.build, target)
}
fn msg_build(
&self,
compiler: Compiler,
what: impl Display,
target: impl Into<Option<TargetSelection>>,
) -> Option<gha::Group> {
self.msg(Kind::Build, compiler.stage, what, compiler.host, target)
}
/// Return a `Group` guard for a [`Step`] that is built for each `--stage`.
fn msg(
&self,
action: impl Into<Kind>,
stage: u32,
what: impl Display,
host: impl Into<Option<TargetSelection>>,
target: impl Into<Option<TargetSelection>>,
) -> Option<gha::Group> {
let action = action.into();
let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}");
let msg = if let Some(target) = target.into() {
let host = host.into().unwrap();
if host == target {
msg(format_args!(" ({target})"))
} else {
msg(format_args!(" ({host} -> {target})"))
}
} else {
msg(format_args!(""))
};
self.group(&msg)
}
/// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`.
fn msg_unstaged(
&self,
action: impl Into<Kind>,
what: impl Display,
target: TargetSelection,
) -> Option<gha::Group> {
let action = action.into();
let msg = format!("{action:?}ing {what} for {target}");
self.group(&msg)
}
fn msg_sysroot_tool(
&self,
action: impl Into<Kind>,
stage: u32,
what: impl Display,
host: TargetSelection,
target: TargetSelection,
) -> Option<gha::Group> {
let action = action.into();
let msg = |fmt| format!("{action:?}ing {what} {fmt}");
let msg = if host == target {
msg(format_args!("(stage{stage} -> stage{}, {target})", stage + 1))
} else {
msg(format_args!("(stage{stage}:{host} -> stage{}:{target})", stage + 1))
};
self.group(&msg)
}
fn group(&self, msg: &str) -> Option<gha::Group> {
self.info(&msg);
match self.config.dry_run {
DryRun::SelfCheck => None,
DryRun::Disabled | DryRun::UserSelected => Some(gha::group(&msg)),
}
}
/// Returns the number of parallel jobs that have been configured for this
/// build.
fn jobs(&self) -> u32 {

View file

@ -21,7 +21,7 @@ use crate::channel;
use crate::config::{Config, TargetSelection};
use crate::util::get_clang_cl_resource_dir;
use crate::util::{self, exe, output, t, up_to_date};
use crate::{CLang, GitRepo};
use crate::{CLang, GitRepo, Kind};
use build_helper::ci::CiEnv;
@ -271,7 +271,7 @@ impl Step for Llvm {
panic!("shared linking to LLVM is not currently supported on {}", target.triple);
}
builder.info(&format!("Building LLVM for {}", target));
let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target);
t!(stamp.remove());
let _time = util::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
@ -813,7 +813,7 @@ impl Step for Lld {
return out_dir;
}
builder.info(&format!("Building LLD for {}", target));
let _guard = builder.msg_unstaged(Kind::Build, "LLD", target);
let _time = util::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
@ -911,7 +911,7 @@ impl Step for Sanitizers {
return runtimes;
}
builder.info(&format!("Building sanitizers for {}", self.target));
let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target);
t!(stamp.remove());
let _time = util::timeit(&builder);
@ -1103,7 +1103,7 @@ impl Step for CrtBeginEnd {
return out_dir;
}
builder.info("Building crtbegin.o and crtend.o");
let _guard = builder.msg_unstaged(Kind::Build, "crtbegin.o and crtend.o", self.target);
t!(fs::create_dir_all(&out_dir));
let mut cfg = cc::Build::new();
@ -1168,7 +1168,7 @@ impl Step for Libunwind {
return out_dir;
}
builder.info(&format!("Building libunwind.a for {}", self.target.triple));
let _guard = builder.msg_unstaged(Kind::Build, "libunwind.a", self.target);
t!(fs::create_dir_all(&out_dir));
let mut cc_cfg = cc::Build::new();

View file

@ -5,7 +5,6 @@
use std::env;
use std::ffi::OsString;
use std::fmt;
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
@ -57,12 +56,12 @@ impl TestKind {
}
}
impl fmt::Display for TestKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match *self {
TestKind::Test => "Testing",
TestKind::Bench => "Benchmarking",
})
impl Into<Kind> for TestKind {
fn into(self) -> Kind {
match self {
TestKind::Test => Kind::Test,
TestKind::Bench => Kind::Bench,
}
}
}
@ -1905,7 +1904,13 @@ impl BookTest {
rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
builder.add_rust_test_threads(&mut rustbook_cmd);
builder.info(&format!("Testing rustbook {}", self.path.display()));
let _guard = builder.msg(
Kind::Test,
compiler.stage,
format_args!("rustbook {}", self.path.display()),
compiler.host,
compiler.host,
);
let _time = util::timeit(&builder);
let toolstate = if try_run(builder, &mut rustbook_cmd) {
ToolState::TestPass
@ -2033,7 +2038,8 @@ impl Step for ErrorIndex {
let mut tool = tool::ErrorIndex::command(builder);
tool.arg("markdown").arg(&output);
builder.info(&format!("Testing error-index stage{}", compiler.stage));
let _guard =
builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
let _time = util::timeit(&builder);
builder.run_quiet(&mut tool);
// The tests themselves need to link to std, so make sure it is
@ -2263,14 +2269,13 @@ impl Step for Crate {
);
}
builder.info(&format!(
"{}{} stage{} ({} -> {})",
let _guard = builder.msg(
test_kind,
crate_description(&self.crates),
compiler.stage,
&compiler.host,
target
));
crate_description(&self.crates),
compiler.host,
target,
);
let _time = util::timeit(&builder);
crate::render_tests::try_run_tests(builder, &mut cargo.into());
}
@ -2386,10 +2391,8 @@ impl Step for CrateRustdoc {
cargo.arg("--quiet");
}
builder.info(&format!(
"{} rustdoc stage{} ({} -> {})",
test_kind, compiler.stage, &compiler.host, target
));
let _guard = builder.msg(test_kind, compiler.stage, "rustdoc", compiler.host, target);
let _time = util::timeit(&builder);
add_flags_and_try_run_tests(builder, &mut cargo.into());
@ -2453,10 +2456,8 @@ impl Step for CrateRustdocJsonTypes {
cargo.arg("'-Ctarget-feature=-crt-static'");
}
builder.info(&format!(
"{} rustdoc-json-types stage{} ({} -> {})",
test_kind, compiler.stage, &compiler.host, target
));
let _guard =
builder.msg(test_kind, compiler.stage, "rustdoc-json-types", compiler.host, target);
let _time = util::timeit(&builder);
add_flags_and_try_run_tests(builder, &mut cargo.into());
@ -2845,7 +2846,7 @@ impl Step for TestHelpers {
return;
}
builder.info("Building test helpers");
let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
t!(fs::create_dir_all(&dst));
let mut cfg = cc::Build::new();
// FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013

View file

@ -11,6 +11,7 @@ use crate::toolstate::ToolState;
use crate::util::{add_dylib_path, exe, t};
use crate::Compiler;
use crate::Mode;
use crate::{gha, Kind};
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum SourceType {
@ -32,41 +33,27 @@ struct ToolBuild {
allow_features: &'static str,
}
fn tooling_output(
mode: Mode,
tool: &str,
build_stage: u32,
host: &TargetSelection,
target: &TargetSelection,
) -> String {
match mode {
// depends on compiler stage, different to host compiler
Mode::ToolRustc => {
if host == target {
format!("Building tool {} (stage{} -> stage{})", tool, build_stage, build_stage + 1)
} else {
format!(
"Building tool {} (stage{}:{} -> stage{}:{})",
tool,
build_stage,
host,
build_stage + 1,
target
)
}
impl Builder<'_> {
fn msg_tool(
&self,
mode: Mode,
tool: &str,
build_stage: u32,
host: &TargetSelection,
target: &TargetSelection,
) -> Option<gha::Group> {
match mode {
// depends on compiler stage, different to host compiler
Mode::ToolRustc => self.msg_sysroot_tool(
Kind::Build,
build_stage,
format_args!("tool {tool}"),
*host,
*target,
),
// doesn't depend on compiler, same as host compiler
_ => self.msg(Kind::Build, build_stage, format_args!("tool {tool}"), *host, *target),
}
// doesn't depend on compiler, same as host compiler
Mode::ToolStd => {
if host == target {
format!("Building tool {} (stage{})", tool, build_stage)
} else {
format!(
"Building tool {} (stage{}:{} -> stage{}:{})",
tool, build_stage, host, build_stage, target
)
}
}
_ => format!("Building tool {} (stage{})", tool, build_stage),
}
}
@ -111,14 +98,13 @@ impl Step for ToolBuild {
if !self.allow_features.is_empty() {
cargo.allow_features(self.allow_features);
}
let msg = tooling_output(
let _guard = builder.msg_tool(
self.mode,
self.tool,
self.compiler.stage,
&self.compiler.host,
&self.target,
);
builder.info(&msg);
let mut cargo = Command::from(cargo);
let is_expected = builder.try_run(&mut cargo);
@ -492,14 +478,13 @@ impl Step for Rustdoc {
cargo.rustflag("--cfg=parallel_compiler");
}
let msg = tooling_output(
let _guard = builder.msg_tool(
Mode::ToolRustc,
"rustdoc",
build_compiler.stage,
&self.compiler.host,
&target,
);
builder.info(&msg);
builder.run(&mut cargo.into());
// Cargo adds a number of paths to the dylib search path on windows, which results in

View file

@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*;
use rustc_hir::def::{DefKind, Namespace, PerNS};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::Mutability;
use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt};
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{bug, ty};
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
@ -772,11 +772,10 @@ fn trait_impls_for<'a>(
module: DefId,
) -> FxHashSet<(DefId, DefId)> {
let tcx = cx.tcx;
let iter = tcx.doc_link_traits_in_scope(module).iter().flat_map(|&trait_| {
trace!("considering explicit impl for trait {:?}", trait_);
let mut impls = FxHashSet::default();
// Look at each trait implementation to see if it's an impl for `did`
tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| {
for &trait_ in tcx.doc_link_traits_in_scope(module) {
tcx.for_each_relevant_impl(trait_, ty, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type.
let impl_type = trait_ref.skip_binder().self_ty();
@ -800,10 +799,13 @@ fn trait_impls_for<'a>(
_ => false,
};
if saw_impl { Some((impl_, trait_)) } else { None }
})
});
iter.collect()
if saw_impl {
impls.insert((impl_, trait_));
}
});
}
impls
}
/// Check for resolve collisions between a trait and its derive.

View file

@ -38,3 +38,27 @@ impl CiEnv {
}
}
}
pub mod gha {
/// All github actions log messages from this call to the Drop of the return value
/// will be grouped and hidden by default in logs. Note that nesting these does
/// not really work.
pub fn group(name: impl std::fmt::Display) -> Group {
if std::env::var_os("GITHUB_ACTIONS").is_some() {
eprintln!("::group::{name}");
}
Group(())
}
/// A guard that closes the current github actions log group on drop.
#[must_use]
pub struct Group(());
impl Drop for Group {
fn drop(&mut self) {
if std::env::var_os("GITHUB_ACTIONS").is_some() {
eprintln!("::endgroup::");
}
}
}
}

View file

@ -8,10 +8,10 @@
#![feature(inline_const)]
#![allow(unreachable_code)]
use std::mem::{transmute, MaybeUninit};
use std::mem::MaybeUninit;
use std::intrinsics::{transmute, transmute_unchecked};
// Some of the cases here are statically rejected by `mem::transmute`, so
// we need to generate custom MIR for those cases to get to codegen.
// Some of these need custom MIR to not get removed by MIR optimizations.
use std::intrinsics::mir::*;
enum Never {}
@ -30,59 +30,35 @@ pub struct Aggregate8(u8);
// CHECK-LABEL: @check_bigger_size(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_bigger_size(x: u16) -> u32 {
// CHECK: call void @llvm.trap
mir!{
{
RET = CastTransmute(x);
Return()
}
}
transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_size(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_smaller_size(x: u32) -> u16 {
// CHECK: call void @llvm.trap
mir!{
{
RET = CastTransmute(x);
Return()
}
}
transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_array(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
// CHECK: call void @llvm.trap
mir!{
{
RET = CastTransmute(x);
Return()
}
}
transmute_unchecked(x)
}
// CHECK-LABEL: @check_bigger_array(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
// CHECK: call void @llvm.trap
mir!{
{
RET = CastTransmute(x);
Return()
}
}
transmute_unchecked(x)
}
// CHECK-LABEL: @check_to_uninhabited(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK: call void @llvm.trap
mir!{
@ -95,7 +71,7 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK-LABEL: @check_from_uninhabited(
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "initial")]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
// CHECK: ret i16 poison
mir!{

View file

@ -0,0 +1,16 @@
#![feature(associated_const_equality)]
// Issue 110549
pub trait TraitWAssocConst {
const A: usize;
}
fn foo<T: TraitWAssocConst<A = 32>>() {}
fn bar<T: TraitWAssocConst>() {
foo::<T>();
//~^ ERROR type mismatch resolving `<T as TraitWAssocConst>::A == 32`
}
fn main() {}

View file

@ -0,0 +1,17 @@
error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 32`
--> $DIR/projection-unspecified-but-bounded.rs:12:11
|
LL | foo::<T>();
| ^ expected `32`, found `<T as TraitWAssocConst>::A`
|
= note: expected constant `32`
found constant `<T as TraitWAssocConst>::A`
note: required by a bound in `foo`
--> $DIR/projection-unspecified-but-bounded.rs:9:28
|
LL | fn foo<T: TraitWAssocConst<A = 32>>() {}
| ^^^^^^ required by this bound in `foo`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.

View file

@ -0,0 +1,16 @@
// compile-flags: --test
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn mac(input: TokenStream) -> TokenStream { loop {} }
#[cfg(test)]
mod test {
#[test]
fn t() { crate::mac!(A) }
//~^ ERROR can't use a procedural macro from the same crate that defines it
//~| HELP you can define integration tests in a directory named `tests`
}

View file

@ -0,0 +1,10 @@
error: can't use a procedural macro from the same crate that defines it
--> $DIR/test-same-crate.rs:13:14
|
LL | fn t() { crate::mac!(A) }
| ^^^^^^^^^^
|
= help: you can define integration tests in a directory named `tests`
error: aborting due to previous error