Skip to content

Rollup of 8 pull requests #136711

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 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
999695b
Make sure to use Receiver trait when extracting object method candidate
compiler-errors Jan 7, 2025
6c4cf30
[AIX] Update tests/ui/wait-forked-but-failed-child.rs to accomodate e…
amy-kwan Feb 4, 2025
427c328
Add ffi tests for pattern types
oli-obk Jan 24, 2025
032bd64
Correctly handle pattern types in FFI safety
oli-obk Jan 24, 2025
c5bc467
Correctly handle pattern types in FFI redeclaration lints
oli-obk Jan 24, 2025
60ed9db
Handle pattern types wrapped in `Option` in FFI checks
oli-obk Jan 28, 2025
e58aa21
Re-enable "jump to def" feature on rustc docs
GuillaumeGomez Jan 20, 2025
4627285
sys: net: Add UEFI stubs
Ayush1325 Feb 6, 2025
9e345fd
tests(std/net): remove outdated `base_port` calculation
jieyouxu Feb 6, 2025
d17a4a7
Add opt_alias_variances and use it in outlives code
compiler-errors Feb 5, 2025
bdaf7a8
Use split_whitespace() when filtering lines in the ps output
amy-kwan Feb 6, 2025
6307270
Move two windows process tests to tests/ui
ChrisDenton Feb 7, 2025
50922da
Rollup merge of #135179 - compiler-errors:arbitrary-self-types-object…
matthiaskrgr Feb 7, 2025
8ca1a3d
Rollup merge of #136193 - oli-obk:pattern-type-ffi-checks, r=chenyukang
matthiaskrgr Feb 7, 2025
c4a2f88
Rollup merge of #136554 - compiler-errors:opt-alias-variances, r=lcnr
matthiaskrgr Feb 7, 2025
39f38ff
Rollup merge of #136556 - amy-kwan:amy-kwan/update_wait-forked-but-fa…
matthiaskrgr Feb 7, 2025
59e807a
Rollup merge of #136589 - GuillaumeGomez:enable-jump-to-def-compiler,…
matthiaskrgr Feb 7, 2025
d22ad0d
Rollup merge of #136615 - Ayush1325:uefi-net-unsupported, r=joboet
matthiaskrgr Feb 7, 2025
523a31d
Rollup merge of #136635 - jieyouxu:base_port, r=joboet
matthiaskrgr Feb 7, 2025
b780412
Rollup merge of #136682 - ChrisDenton:move-win-proc-tests, r=joboet
matthiaskrgr Feb 7, 2025
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
12 changes: 7 additions & 5 deletions compiler/rustc_borrowck/src/type_check/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ where
return;
}

match ty.kind() {
match *ty.kind() {
ty::Closure(_, args) => {
// Skip lifetime parameters of the enclosing item(s)

Expand Down Expand Up @@ -316,10 +316,12 @@ where
args.as_coroutine().resume_ty().visit_with(self);
}

ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// Skip lifetime parameters that are not captures.
let variances = self.tcx.variances_of(*def_id);

ty::Alias(kind, ty::AliasTy { def_id, args, .. })
if let Some(variances) = self.tcx.opt_alias_variances(kind, def_id) =>
{
// Skip lifetime parameters that are not captured, since they do
// not need member constraints registered for them; we'll erase
// them (and hopefully in the future replace them with placeholders).
for (v, s) in std::iter::zip(variances, args.iter()) {
if *v != ty::Bivariant {
s.visit_with(self);
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// yield an object-type (e.g., `&Object` or `Box<Object>`
// etc).

// FIXME: this feels, like, super dubious
self.fcx
.autoderef(self.span, self_ty)
let mut autoderef = self.fcx.autoderef(self.span, self_ty);

// We don't need to gate this behind arbitrary self types
// per se, but it does make things a bit more gated.
if self.tcx.features().arbitrary_self_types()
|| self.tcx.features().arbitrary_self_types_pointers()
{
autoderef = autoderef.use_receiver_trait();
}

autoderef
.include_raw_pointers()
.find_map(|(ty, _)| match ty.kind() {
ty::Dynamic(data, ..) => Some(closure(
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_infer/src/infer/outlives/for_liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where
return ty.super_visit_with(self);
}

match ty.kind() {
match *ty.kind() {
// We can prove that an alias is live two ways:
// 1. All the components are live.
//
Expand Down Expand Up @@ -95,11 +95,9 @@ where
assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS));
r.visit_with(self);
} else {
// Skip lifetime parameters that are not captures.
let variances = match kind {
ty::Opaque => Some(self.tcx.variances_of(*def_id)),
_ => None,
};
// Skip lifetime parameters that are not captured, since they do
// not need to be live.
let variances = tcx.opt_alias_variances(kind, def_id);

for (idx, s) in args.iter().enumerate() {
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,13 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
let kind = alias_ty.kind(self.tcx);
if approx_env_bounds.is_empty()
&& trait_bounds.is_empty()
&& (alias_ty.has_infer_regions() || is_opaque)
&& (alias_ty.has_infer_regions() || kind == ty::Opaque)
{
debug!("no declared bounds");
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
let opt_variances = self.tcx.opt_alias_variances(kind, alias_ty.def_id);
self.args_must_outlive(alias_ty.args, origin, region, opt_variances);
return;
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/outlives/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {

#[instrument(level = "debug", skip(self))]
pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> {
let alias_ty_as_ty = alias_ty.to_ty(self.tcx);

// Search the env for where clauses like `P: 'a`.
let env_bounds = self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder| {
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars()
&& ty == alias_ty_as_ty
&& let ty::Alias(_, alias_ty_from_bound) = *ty.kind()
&& alias_ty_from_bound == alias_ty
{
// Micro-optimize if this is an exact match (this
// occurs often when there are no region variables
Expand All @@ -127,7 +126,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
compute_alias_components_recursive(self.tcx, alias_ty_as_ty, &mut components);
let kind = alias_ty.kind(self.tcx);
compute_alias_components_recursive(self.tcx, kind, alias_ty, &mut components);
self.bound_from_components(&components)
};

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
if tcx.sess.opts.unstable_opts.input_stats {
rustc_passes::input_stats::print_hir_stats(tcx);
}
#[cfg(debug_assertions)]
// When using rustdoc's "jump to def" feature, it enters this code and `check_crate`
// is not defined. So we need to cfg it out.
#[cfg(all(not(doc), debug_assertions))]
rustc_passes::hir_id_validator::check_crate(tcx);
let sess = tcx.sess;
sess.time("misc_checking_1", || {
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,6 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`

lint_improper_ctypes_opaque = opaque types have no C equivalent

lint_improper_ctypes_pat_help = consider using the base type instead

lint_improper_ctypes_pat_reason = pattern types have no C equivalent
lint_improper_ctypes_slice_help = consider using a raw pointer instead

lint_improper_ctypes_slice_reason = slices have no C equivalent
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
if let ty::Adt(def, args) = *ty.kind() {
let is_transparent = def.repr().transparent();
let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
debug!(
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
ty, is_transparent, is_non_null
);
debug!(?ty, is_transparent, is_non_null);
if is_transparent && !is_non_null {
debug_assert_eq!(def.variants().len(), 1);
let v = &def.variant(FIRST_VARIANT);
Expand Down Expand Up @@ -378,14 +375,14 @@ fn structurally_same_type_impl<'tcx>(

// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
// enum layout optimisation is being applied.
(Adt(..), _) if is_primitive_or_pointer(b) => {
(Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => {
if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
a_inner == b
} else {
false
}
}
(_, Adt(..)) if is_primitive_or_pointer(a) => {
(_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => {
if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
b_inner == a
} else {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(trait_upcasting)]
#![feature(try_blocks)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end

Expand Down
148 changes: 91 additions & 57 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,37 @@ fn ty_is_known_nonnull<'tcx>(
.filter_map(|variant| transparent_newtype_field(tcx, variant))
.any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode))
}
ty::Pat(base, pat) => {
ty_is_known_nonnull(tcx, typing_env, *base, mode)
|| Option::unwrap_or_default(
try {
match **pat {
ty::PatternKind::Range { start, end, include_end } => {
match (start, end) {
(Some(start), None) => {
start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0
}
(Some(start), Some(end)) => {
let start =
start.try_to_value()?.try_to_bits(tcx, typing_env)?;
let end =
end.try_to_value()?.try_to_bits(tcx, typing_env)?;

if include_end {
// This also works for negative numbers, as we just need
// to ensure we aren't wrapping over zero.
start > 0 && end >= start
} else {
start > 0 && end > start
}
}
_ => false,
}
}
}
},
)
}
_ => false,
}
}
Expand Down Expand Up @@ -900,9 +931,8 @@ fn get_nullable_type<'tcx>(
};
return get_nullable_type(tcx, typing_env, inner_field_ty);
}
ty::Int(ty) => Ty::new_int(tcx, ty),
ty::Uint(ty) => Ty::new_uint(tcx, ty),
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base),
ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
// As these types are always non-null, the nullable equivalent of
// `Option<T>` of these types are their raw pointer counterparts.
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
Expand Down Expand Up @@ -958,63 +988,69 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
ckind: CItemKind,
) -> Option<Ty<'tcx>> {
debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty);
if let ty::Adt(ty_def, args) = ty.kind() {
let field_ty = match &ty_def.variants().raw[..] {
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
([], [field]) | ([field], []) => field.ty(tcx, args),
([field1], [field2]) => {
let ty1 = field1.ty(tcx, args);
let ty2 = field2.ty(tcx, args);

if is_niche_optimization_candidate(tcx, typing_env, ty1) {
ty2
} else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
ty1
} else {
return None;
match ty.kind() {
ty::Adt(ty_def, args) => {
let field_ty = match &ty_def.variants().raw[..] {
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
([], [field]) | ([field], []) => field.ty(tcx, args),
([field1], [field2]) => {
let ty1 = field1.ty(tcx, args);
let ty2 = field2.ty(tcx, args);

if is_niche_optimization_candidate(tcx, typing_env, ty1) {
ty2
} else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
ty1
} else {
return None;
}
}
}
_ => return None,
},
_ => return None,
},
_ => return None,
};
};

if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
return None;
}
if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
return None;
}

// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
// If the computed size for the field and the enum are different, the nonnull optimization isn't
// being applied (and we've got a problem somewhere).
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
bug!("improper_ctypes: Option nonnull optimization not applied?");
}
// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
// If the computed size for the field and the enum are different, the nonnull optimization isn't
// being applied (and we've got a problem somewhere).
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
bug!("improper_ctypes: Option nonnull optimization not applied?");
}

// Return the nullable type this Option-like enum can be safely represented with.
let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
bug!("should be able to compute the layout of non-polymorphic type");
}
// Return the nullable type this Option-like enum can be safely represented with.
let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
bug!("should be able to compute the layout of non-polymorphic type");
}

let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
match field_ty_scalar.valid_range(&tcx) {
WrappingRange { start: 0, end }
if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
{
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start: 1, .. } => {
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start, end } => {
unreachable!("Unhandled start and end range: ({}, {})", start, end)
}
};
let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
match field_ty_scalar.valid_range(&tcx) {
WrappingRange { start: 0, end }
if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
{
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start: 1, .. } => {
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start, end } => {
unreachable!("Unhandled start and end range: ({}, {})", start, end)
}
};
}
None
}
ty::Pat(base, pat) => match **pat {
ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, *base),
},
_ => None,
}
None
}

impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
Expand Down Expand Up @@ -1249,11 +1285,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
help: Some(fluent::lint_improper_ctypes_char_help),
},

ty::Pat(..) => FfiUnsafe {
ty,
reason: fluent::lint_improper_ctypes_pat_reason,
help: Some(fluent::lint_improper_ctypes_pat_help),
},
// It's just extra invariants on the type that you need to uphold,
// but only the base type is relevant for being representable in FFI.
ty::Pat(base, ..) => self.check_type_for_ffi(acc, base),

ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.variances_of(def_id)
}

fn opt_alias_variances(
self,
kind: impl Into<ty::AliasTermKind>,
def_id: DefId,
) -> Option<&'tcx [ty::Variance]> {
self.opt_alias_variances(kind, def_id)
}

fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
self.type_of(def_id)
}
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,29 @@ impl<'tcx> TyCtxt<'tcx> {

ty
}

// Computes the variances for an alias (opaque or RPITIT) that represent
// its (un)captured regions.
pub fn opt_alias_variances(
self,
kind: impl Into<ty::AliasTermKind>,
def_id: DefId,
) -> Option<&'tcx [ty::Variance]> {
match kind.into() {
ty::AliasTermKind::ProjectionTy => {
if self.is_impl_trait_in_trait(def_id) {
Some(self.variances_of(def_id))
} else {
None
}
}
ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
ty::AliasTermKind::InherentTy
| ty::AliasTermKind::WeakTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => None,
}
}
}

struct OpaqueTypeExpander<'tcx> {
Expand Down
Loading
Loading