Skip to content

Rollup of 6 pull requests #143081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2577,8 +2577,7 @@ pub enum TyPatKind {
pub enum TraitObjectSyntax {
// SAFETY: When adding new variants make sure to update the `Tag` impl.
Dyn = 0,
DynStar = 1,
None = 2,
None = 1,
}

/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
Expand All @@ -2594,8 +2593,7 @@ unsafe impl Tag for TraitObjectSyntax {
unsafe fn from_usize(tag: usize) -> Self {
match tag {
0 => TraitObjectSyntax::Dyn,
1 => TraitObjectSyntax::DynStar,
2 => TraitObjectSyntax::None,
1 => TraitObjectSyntax::None,
_ => unreachable!(),
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
);
gate_all!(associated_const_equality, "associated const equality is incomplete");
gate_all!(yeet_expr, "`do yeet` expression is experimental");
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(ergonomic_clones, "ergonomic clones are experimental");
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,6 @@ impl<'a> State<'a> {
ast::TyKind::TraitObject(bounds, syntax) => {
match syntax {
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
ast::TraitObjectSyntax::None => {}
}
self.print_type_bounds(bounds);
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,17 @@ impl Deprecation {
}
}

/// There are three valid forms of the attribute:
/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
/// `#[used(compiler)]`
/// `#[used(linker)]`
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic, PrintAttribute)]
pub enum UsedBy {
Compiler,
Linker,
}

/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
Expand Down Expand Up @@ -285,5 +296,8 @@ pub enum AttributeKind {

/// Represents `#[track_caller]`
TrackCaller(Span),

/// Represents `#[used]`
Used { used_by: UsedBy, span: Span },
// tidy-alphabetical-end
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl AttributeKind {
PubTransparent(..) => Yes,
SkipDuringMethodDispatch { .. } => No,
TrackCaller(..) => Yes,
Used { .. } => No,
}
}
}
83 changes: 82 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr};
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
use rustc_feature::{AttributeTemplate, template};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
Expand Down Expand Up @@ -228,3 +228,84 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser {
Some(AttributeKind::NoMangle(cx.attr_span))
}
}

#[derive(Default)]
pub(crate) struct UsedParser {
first_compiler: Option<Span>,
first_linker: Option<Span>,
}

// A custom `AttributeParser` is used rather than a Simple attribute parser because
// - Specifying two `#[used]` attributes is a warning (but will be an error in the future)
// - But specifying two conflicting attributes: `#[used(compiler)]` and `#[used(linker)]` is already an error today
// We can change this to a Simple parser once the warning becomes an error
impl<S: Stage> AttributeParser<S> for UsedParser {
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
&[sym::used],
template!(Word, List: "compiler|linker"),
|group: &mut Self, cx, args| {
let used_by = match args {
ArgParser::NoArgs => UsedBy::Linker,
ArgParser::List(list) => {
let Some(l) = list.single() else {
cx.expected_single_argument(list.span);
return;
};

match l.meta_item().and_then(|i| i.path().word_sym()) {
Some(sym::compiler) => {
if !cx.features().used_with_arg() {
feature_err(
&cx.sess(),
sym::used_with_arg,
cx.attr_span,
"`#[used(compiler)]` is currently unstable",
)
.emit();
}
UsedBy::Compiler
}
Some(sym::linker) => {
if !cx.features().used_with_arg() {
feature_err(
&cx.sess(),
sym::used_with_arg,
cx.attr_span,
"`#[used(linker)]` is currently unstable",
)
.emit();
}
UsedBy::Linker
}
_ => {
cx.expected_specific_argument(l.span(), vec!["compiler", "linker"]);
return;
}
}
}
ArgParser::NameValue(_) => return,
};

let target = match used_by {
UsedBy::Compiler => &mut group.first_compiler,
UsedBy::Linker => &mut group.first_linker,
};

let attr_span = cx.attr_span;
if let Some(prev) = *target {
cx.warn_unused_duplicate(prev, attr_span);
} else {
*target = Some(attr_span);
}
},
)];

fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
Some(match (self.first_compiler, self.first_linker) {
(_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span },
(Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
(None, None) => return None,
})
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
use crate::attributes::codegen_attrs::{
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser,
UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
Expand Down Expand Up @@ -103,6 +104,7 @@ attribute_parsers!(
ConstStabilityParser,
NakedParser,
StabilityParser,
UsedParser,
// tidy-alphabetical-end

// tidy-alphabetical-start
Expand Down
38 changes: 3 additions & 35 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt,
TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
UserArgs, UserTypeAnnotationIndex, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::move_paths::MoveData;
Expand Down Expand Up @@ -1233,38 +1233,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);
}

CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
// get the constraints from the target type (`dyn* Clone`)
//
// apply them to prove that the source type `Foo` implements `Clone` etc
let (existential_predicates, region) = match ty.kind() {
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
_ => panic!("Invalid dyn* cast_ty"),
};

let self_ty = op.ty(self.body, tcx);

let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
self.prove_predicates(
existential_predicates
.iter()
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
location.to_locations(),
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
);

let outlives_predicate = tcx.mk_predicate(Binder::dummy(
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
ty::OutlivesPredicate(self_ty, *region),
)),
));
self.prove_predicate(
outlives_predicate,
location.to_locations(),
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
);
}

CastKind::PointerCoercion(
PointerCoercion::MutToConstPointer,
coercion_source,
Expand Down
45 changes: 0 additions & 45 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,51 +753,6 @@ pub(crate) fn codegen_drop<'tcx>(
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
fx.bcx.ins().jump(ret_block, &[]);
}
ty::Dynamic(_, _, ty::DynStar) => {
// IN THIS ARM, WE HAVE:
// ty = *mut (dyn* Trait)
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
//
// args = [ * ]
// |
// v
// ( Data, Vtable )
// |
// v
// /-------\
// | ... |
// \-------/
//
//
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
//
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
// vtable = (*args[0]).1 // loads the vtable out
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
//
// SO THEN WE CAN USE THE ABOVE CODE.
let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);

let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0);
let target_block = fx.get_block(target);
let continued = fx.bcx.create_block();
fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]);
fx.bcx.switch_to_block(continued);

let virtual_drop = Instance {
def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0),
args: drop_instance.args,
};
let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx)
.fn_abi_of_instance(virtual_drop, ty::List::empty());

let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = fx.bcx.import_signature(sig);
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
// FIXME implement cleanup on exceptions
fx.bcx.ins().jump(ret_block, &[]);
}
_ => {
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));

Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,14 +778,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
let operand = codegen_operand(fx, operand);
crate::unsize::coerce_unsized_into(fx, operand, lval);
}
Rvalue::Cast(
CastKind::PointerCoercion(PointerCoercion::DynStar, _),
ref operand,
_,
) => {
let operand = codegen_operand(fx, operand);
crate::unsize::coerce_dyn_star(fx, operand, lval);
}
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
let operand = codegen_operand(fx, operand);
lval.write_cvalue_transmute(fx, operand);
Expand Down
33 changes: 0 additions & 33 deletions compiler/rustc_codegen_cranelift/src/unsize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,6 @@ fn unsize_ptr<'tcx>(
}
}

/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
pub(crate) fn cast_to_dyn_star<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
src: Value,
src_ty_and_layout: TyAndLayout<'tcx>,
dst_ty: Ty<'tcx>,
old_info: Option<Value>,
) -> (Value, Value) {
assert!(
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"destination type must be a dyn*"
);
(src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
}

/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub(crate) fn coerce_unsized_into<'tcx>(
Expand Down Expand Up @@ -174,24 +159,6 @@ pub(crate) fn coerce_unsized_into<'tcx>(
}
}

pub(crate) fn coerce_dyn_star<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
src: CValue<'tcx>,
dst: CPlace<'tcx>,
) {
let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
let (data, vtable) = src.load_scalar_pair(fx);
(data, Some(vtable))
} else {
let data = src.load_scalar(fx);
(data, None)
};

let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);

dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
}

// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs

pub(crate) fn size_and_align_of<'tcx>(
Expand Down
37 changes: 0 additions & 37 deletions compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,43 +121,6 @@ impl<'tcx> CValue<'tcx> {
}
}

// FIXME remove
/// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
/// vtable pointer.
pub(crate) fn dyn_star_force_data_on_stack(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,
) -> (Value, Value) {
assert!(self.1.ty.is_dyn_star());

match self.0 {
CValueInner::ByRef(ptr, None) => {
let (a_scalar, b_scalar) = match self.1.backend_repr {
BackendRepr::ScalarPair(a, b) => (a, b),
_ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
};
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
let mut flags = MemFlags::new();
flags.set_notrap();
let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
(ptr.get_addr(fx), vtable)
}
CValueInner::ByValPair(data, vtable) => {
let data_ptr = fx.create_stack_slot(
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
);
data_ptr.store(fx, data, MemFlags::trusted());

(data_ptr.get_addr(fx), vtable)
}
CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
unreachable!("dyn_star_force_data_on_stack({:?})", self)
}
}
}

pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
match self.0 {
CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
Expand Down
Loading
Loading