Skip to content
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

[beta] backport #115901

Merged
merged 4 commits into from
Sep 17, 2023
Merged
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
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use std::ops::{Index, IndexMut};

pub(super) struct Locals<'tcx, V> {
values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
}
Expand Down Expand Up @@ -36,17 +35,18 @@ impl<'tcx, V> Locals<'tcx, V> {
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value>>) {
assert!(self.locals.values.is_empty());

// FIXME(#115215): After #115025 get's merged this might not be necessary
for (local, value) in values.into_iter().enumerate() {
match value {
LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
LocalRef::Operand(op) => {
let local = mir::Local::from_usize(local);
let expected_ty = self.monomorphize(self.mir.local_decls[local].ty);
assert_eq!(expected_ty, op.layout.ty, "unexpected initial operand type");
if expected_ty != op.layout.ty {
warn!("Unexpected initial operand type. See the issues/114858");
}
}
}

self.locals.values.push(value);
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,8 @@ impl<'a> Parser<'a> {
) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?;

if !matches!(syntax_loc, Some(PatternLocation::FunctionParameter))
if self.may_recover()
&& !matches!(syntax_loc, Some(PatternLocation::FunctionParameter))
&& self.check_noexpect(&token::Lt)
&& self.look_ahead(1, |t| t.can_begin_type())
{
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_resolve/src/effective_visibilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,14 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
// If the binding is ambiguous, put the root ambiguity binding and all reexports
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
let is_ambiguity =
|binding: NameBinding<'a>, warn: bool| binding.ambiguity.is_some() && !warn;
let mut parent_id = ParentId::Def(module_id);
let mut warn_ambiguity = binding.warn_ambiguity;
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
self.update_import(binding, parent_id);

if binding.ambiguity.is_some() {
if is_ambiguity(binding, warn_ambiguity) {
// Stop at the root ambiguity, further bindings in the chain should not
// be reexported because the root ambiguity blocks any access to them.
// (Those further bindings are most likely not ambiguities themselves.)
Expand All @@ -141,9 +144,9 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {

parent_id = ParentId::Import(binding);
binding = nested_binding;
warn_ambiguity |= nested_binding.warn_ambiguity;
}

if binding.ambiguity.is_none()
if !is_ambiguity(binding, warn_ambiguity)
&& let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
self.update_def(def_id, binding.vis.expect_local(), parent_id);
}
Expand Down
24 changes: 22 additions & 2 deletions compiler/rustc_ty_utils/src/needs_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,32 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
// needs drop.
let adt_has_dtor =
|adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
let res =
drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some();
let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false)
.filter(filter_array_elements(tcx, query.param_env))
.next()
.is_some();

debug!("needs_drop_raw({:?}) = {:?}", query, res);
res
}

/// HACK: in order to not mistakenly assume that `[PhantomData<T>; N]` requires drop glue
/// we check the element type for drop glue. The correct fix would be looking at the
/// entirety of the code around `needs_drop_components` and this file and come up with
/// logic that is easier to follow while not repeating any checks that may thus diverge.
fn filter_array_elements<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> impl Fn(&Result<Ty<'tcx>, AlwaysRequiresDrop>) -> bool {
move |ty| match ty {
Ok(ty) => match *ty.kind() {
ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)),
_ => true,
},
Err(AlwaysRequiresDrop) => true,
}
}

fn has_significant_drop_raw<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
Expand All @@ -37,6 +56,7 @@ fn has_significant_drop_raw<'tcx>(
adt_consider_insignificant_dtor(tcx),
true,
)
.filter(filter_array_elements(tcx, query.param_env))
.next()
.is_some();
debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
Expand Down
48 changes: 48 additions & 0 deletions tests/ui/codegen/subtyping-enforces-type-equality.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// ignore-pass
// build-pass
// edition:2021
use std::future::Future;
use std::pin::Pin;

type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;

fn main() {
let _ = wrapper_call(handler);
}

async fn wrapper_call(handler: impl Handler) {
handler.call().await;
}
async fn handler() {
f(&()).await;
}
async fn f<'a>(db: impl Acquire<'a>) {
db.acquire().await;
}

trait Handler {
type Future: Future;
fn call(self) -> Self::Future;
}

impl<Fut, F> Handler for F
where
F: Fn() -> Fut,
Fut: Future,
{
type Future = Fut;
fn call(self) -> Self::Future {
loop {}
}
}

trait Acquire<'a> {
type Connection;
fn acquire(self) -> BoxFuture<Self::Connection>;
}
impl<'a> Acquire<'a> for &'a () {
type Connection = Self;
fn acquire(self) -> BoxFuture<Self> {
loop {}
}
}
1 change: 1 addition & 0 deletions tests/ui/codegen/subtyping-enforces-type-equality.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type. See the issues/114858
17 changes: 17 additions & 0 deletions tests/ui/consts/drop-maybe_uninit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// build-pass

pub const fn f<T, const N: usize>(_: [std::mem::MaybeUninit<T>; N]) {}

pub struct Blubb<T>(*const T);

pub const fn g<T, const N: usize>(_: [Blubb<T>; N]) {}

pub struct Blorb<const N: usize>([String; N]);

pub const fn h(_: Blorb<0>) {}

pub struct Wrap(Blorb<0>);

pub const fn i(_: Wrap) {}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/imports/ambiguous-4.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// check-pass
// build-pass
// aux-build: ../ambiguous-4-extern.rs

extern crate ambiguous_4_extern;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Regression test for issue #115780.
// Ensure that we don't emit a parse error for the token sequence `Ident "<" Ty` in pattern position
// if we are inside a macro call since it can be valid input for a subsequent macro rule.
// See also #103534.

// check-pass

macro_rules! mdo {
($p: pat =<< $e: expr ; $( $t: tt )*) => {
$e.and_then(|$p| mdo! { $( $t )* })
};
(ret<$ty: ty> $e: expr;) => { Some::<$ty>($e) };
}

fn main() {
mdo! {
x_val =<< Some(0);
y_val =<< Some(1);
ret<(i32, i32)> (x_val, y_val);
};
}