Skip to content

Commit

Permalink
Auto merge of #122012 - matthiaskrgr:rollup-bzqjj2n, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 10 pull requests

Successful merges:

 - #121213 (Add an example to demonstrate how Rc::into_inner works)
 - #121262 (Add vector time complexity)
 - #121287 (Clarify/add `must_use` message for Rc/Arc/Weak::into_raw.)
 - #121664 (Adjust error `yield`/`await` lowering)
 - #121826 (Use root obligation on E0277 for some cases)
 - #121838 (Use the correct logic for nested impl trait in assoc types)
 - #121913 (Don't panic when waiting on poisoned queries)
 - #121987 (pattern analysis: abort on arity mismatch)
 - #121993 (Avoid using unnecessary queries when printing the query stack in panics)
 - #121997 (interpret/cast: make more matches on FloatTy properly exhaustive)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 5, 2024
2 parents 5a1e544 + 92ff43d commit 41d97c8
Show file tree
Hide file tree
Showing 71 changed files with 435 additions and 284 deletions.
52 changes: 43 additions & 9 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(hir::CoroutineKind::Coroutine(_))
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
| None => {
return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
await_kw_span,
item_span: self.current_item,
}));
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
// is not accidentally orphaned.
let stmt_id = self.next_id();
let expr_err = self.expr(
expr.span,
hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
await_kw_span,
item_span: self.current_item,
})),
);
return hir::ExprKind::Block(
self.block_all(
expr.span,
arena_vec![self; hir::Stmt {
hir_id: stmt_id,
kind: hir::StmtKind::Semi(expr),
span: expr.span,
}],
Some(self.arena.alloc(expr_err)),
),
None,
);
}
};

Expand Down Expand Up @@ -1496,12 +1514,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
let yielded =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));

let is_async_gen = match self.coroutine_kind {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
return hir::ExprKind::Err(
self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
// is not accidentally orphaned.
let stmt_id = self.next_id();
let expr_err = self.expr(
yielded.span,
hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
);
return hir::ExprKind::Block(
self.block_all(
yielded.span,
arena_vec![self; hir::Stmt {
hir_id: stmt_id,
kind: hir::StmtKind::Semi(yielded),
span: yielded.span,
}],
Some(self.arena.alloc(expr_err)),
),
None,
);
}
Some(hir::CoroutineKind::Coroutine(_)) => {
Expand Down Expand Up @@ -1531,9 +1568,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};

let yielded =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));

if is_async_gen {
// `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
// This ensures that we store our resumed `ResumeContext` correctly, and also that
Expand Down
58 changes: 35 additions & 23 deletions compiler/rustc_const_eval/src/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
use rustc_type_ir::TyKind::*;

let val = match src.layout.ty.kind() {
// Floating point
Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
_ => {
bug!("Can't cast 'Float' type into {}", cast_to.ty);
}
let Float(fty) = src.layout.ty.kind() else {
bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty)
};
let val = match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
FloatTy::F128 => unimplemented!("f16_f128"),
};
Ok(ImmTy::from_scalar(val, cast_to))
}
Expand Down Expand Up @@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);

Ok(match *cast_ty.kind() {
// int -> int
Int(_) | Uint(_) => {
let size = match *cast_ty.kind() {
Int(t) => Integer::from_int_ty(self, t).size(),
Expand All @@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Scalar::from_uint(v, size)
}

Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value),

Char => {
// `u8` to `char` cast
Scalar::from_u32(u8::try_from(v).unwrap().into())
// signed int -> float
Float(fty) if signed => {
let v = v as i128;
match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value),
FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value),
FloatTy::F128 => unimplemented!("f16_f128"),
}
}
// unsigned int -> float
Float(fty) => match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value),
FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value),
FloatTy::F128 => unimplemented!("f16_f128"),
},

// u8 -> char
Char => Scalar::from_u32(u8::try_from(v).unwrap().into()),

// Casts to bool are not permitted by rustc, no need to handle them here.
_ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty),
Expand Down Expand Up @@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let v = f.to_i128(size.bits_usize()).value;
Scalar::from_int(v, size)
}
// float -> f32
Float(FloatTy::F32) => {
Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value))
}
// float -> f64
Float(FloatTy::F64) => {
Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value))
}
// float -> float
Float(fty) => match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F128 => unimplemented!("f16_f128"),
},
// That's it.
_ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty),
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}

match ty.kind() {
match ty.peel_refs().kind() {
ty::Param(param) => {
let generics = self.tcx.generics_of(self.body_id);
let generic_param = generics.type_param(&param, self.tcx);
Expand All @@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
ty::Alias(ty::AliasKind::Opaque, _) => {
ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => {
for unsatisfied in unsatisfied_predicates.iter() {
if is_iterator_predicate(unsatisfied.0, self.tcx) {
return true;
Expand Down
22 changes: 15 additions & 7 deletions compiler/rustc_pattern_analysis/src/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,19 +1001,26 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> {
/// Only call if `ctor.is_covered_by(self.head().ctor())` is true.
fn pop_head_constructor(
&self,
cx: &Cx,
ctor: &Constructor<Cx>,
ctor_arity: usize,
ctor_is_relevant: bool,
) -> PatStack<'p, Cx> {
) -> Result<PatStack<'p, Cx>, Cx::Error> {
// We pop the head pattern and push the new fields extracted from the arguments of
// `self.head()`.
let mut new_pats = self.head().specialize(ctor, ctor_arity);
if new_pats.len() != ctor_arity {
return Err(cx.bug(format_args!(
"uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})",
self.head().as_pat().unwrap()
)));
}
new_pats.extend_from_slice(&self.pats[1..]);
// `ctor` is relevant for this row if it is the actual constructor of this row, or if the
// row has a wildcard and `ctor` is relevant for wildcards.
let ctor_is_relevant =
!matches!(self.head().ctor(), Constructor::Wildcard) || ctor_is_relevant;
PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant }
Ok(PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant })
}
}

Expand Down Expand Up @@ -1083,18 +1090,19 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
/// Only call if `ctor.is_covered_by(self.head().ctor())` is true.
fn pop_head_constructor(
&self,
cx: &Cx,
ctor: &Constructor<Cx>,
ctor_arity: usize,
ctor_is_relevant: bool,
parent_row: usize,
) -> MatrixRow<'p, Cx> {
MatrixRow {
pats: self.pats.pop_head_constructor(ctor, ctor_arity, ctor_is_relevant),
) -> Result<MatrixRow<'p, Cx>, Cx::Error> {
Ok(MatrixRow {
pats: self.pats.pop_head_constructor(cx, ctor, ctor_arity, ctor_is_relevant)?,
parent_row,
is_under_guard: self.is_under_guard,
useful: false,
intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
}
})
}
}

Expand Down Expand Up @@ -1217,7 +1225,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
};
for (i, row) in self.rows().enumerate() {
if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?;
matrix.expand_and_push(new_row);
}
}
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_middle::dep_graph::{
use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
use rustc_middle::query::Key;
use rustc_middle::ty::print::with_reduced_queries;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
Expand Down Expand Up @@ -304,22 +305,26 @@ pub(crate) fn create_query_frame<
kind: DepKind,
name: &'static str,
) -> QueryStackFrame {
// If reduced queries are requested, we may be printing a query stack due
// to a panic. Avoid using `default_span` and `def_kind` in that case.
let reduce_queries = with_reduced_queries();

// Avoid calling queries while formatting the description
let description = ty::print::with_no_queries!(do_describe(tcx, key));
let description = if tcx.sess.verbose_internals() {
format!("{description} [{name:?}]")
} else {
description
};
let span = if kind == dep_graph::dep_kinds::def_span {
let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries {
// The `def_span` query is used to calculate `default_span`,
// so exit to avoid infinite recursion.
None
} else {
Some(key.default_span(tcx))
};
let def_id = key.key_as_def_id();
let def_kind = if kind == dep_graph::dep_kinds::def_kind {
let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
// Try to avoid infinite recursion.
None
} else {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_query_system/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,8 @@ where
let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock();

match lock.get(&key) {
Some(QueryResult::Poisoned) => {
panic!("query '{}' not cached due to poisoning", query.name())
}
// The query we waited on panicked. Continue unwinding here.
Some(QueryResult::Poisoned) => FatalError.raise(),
_ => panic!(
"query '{}' result must be in the cache or the query must be poisoned after a wait",
query.name()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,59 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let trait_ref = trait_predicate.to_poly_trait_ref();

if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
// Let's use the root obligation as the main message, when we care about the
// most general case ("X doesn't implement Pattern<'_>") over the case that
// happened to fail ("char doesn't implement Fn(&mut char)").
//
// We rely on a few heuristics to identify cases where this root
// obligation is more important than the leaf obligation:
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
ty::ClauseKind::Trait(root_pred)
) = root_obligation.predicate.kind().skip_binder()
&& !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
&& !root_pred.self_ty().has_escaping_bound_vars()
// The type of the leaf predicate is (roughly) the same as the type
// from the root predicate, as a proxy for "we care about the root"
// FIXME: this doesn't account for trivial derefs, but works as a first
// approximation.
&& (
// `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
self.can_eq(
obligation.param_env,
trait_predicate.self_ty().skip_binder(),
root_pred.self_ty().peel_refs(),
)
// `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
|| self.can_eq(
obligation.param_env,
trait_predicate.self_ty().skip_binder(),
root_pred.self_ty(),
)
)
// The leaf trait and the root trait are different, so as to avoid
// talking about `&mut T: Trait` and instead remain talking about
// `T: Trait` instead
&& trait_predicate.def_id() != root_pred.def_id()
// The root trait is not `Unsize`, as to avoid talking about it in
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
{
(
self.resolve_vars_if_possible(
root_obligation.predicate.kind().rebind(root_pred),
),
root_obligation,
)
} else {
(trait_predicate, &obligation)
};
let trait_ref = main_trait_predicate.to_poly_trait_ref();

if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation,
trait_ref,
) {
return guar;
}

Expand Down Expand Up @@ -459,8 +509,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
notes,
parent_label,
append_const_msg,
} = self.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);

} = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
let is_unsize =
Expand All @@ -483,7 +532,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
};

let err_msg = self.get_standard_error_message(
&trait_predicate,
&main_trait_predicate,
message,
predicate_is_const,
append_const_msg,
Expand Down
Loading

0 comments on commit 41d97c8

Please sign in to comment.