Auto merge of #89882 - matthiaskrgr:rollup-1dh7pz8, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #89390 (Fix incorrect Box::pin suggestion) - #89433 (Fix ctrl-c causing reads of stdin to return empty on Windows.) - #89823 (Switch order of terms to prevent overflow) - #89865 (Allow static linking LLVM with ThinLTO) - #89873 (Add missing word to `FromStr` trait documentation) - #89878 (Fix missing remaining compiler specific cfg information) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e1e9319d93
14 changed files with 121 additions and 50 deletions
|
@ -558,7 +558,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
|
|||
fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
|
||||
let infcx = self.infcx;
|
||||
let index =
|
||||
self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1;
|
||||
self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
|
||||
let universe = self.universe_indices[index].unwrap_or_else(|| {
|
||||
for i in self.universe_indices.iter_mut().take(index + 1) {
|
||||
*i = i.or_else(|| Some(infcx.create_next_universe()))
|
||||
|
|
|
@ -42,7 +42,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
|
||||
|
@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
.and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations))
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||
// First, remove any resolved type variables (at the top level, at least):
|
||||
let a = self.shallow_resolve(a);
|
||||
|
@ -933,14 +934,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Same as `try_coerce()`, but without side-effects.
|
||||
///
|
||||
/// Returns false if the coercion creates any obligations that result in
|
||||
/// errors.
|
||||
pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
|
||||
let source = self.resolve_vars_with_obligations(expr_ty);
|
||||
debug!("coercion::can({:?} -> {:?})", source, target);
|
||||
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
|
||||
|
||||
let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
|
||||
// We don't ever need two-phase here since we throw out the result of the coercion
|
||||
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
|
||||
self.probe(|_| coerce.coerce(source, target)).is_ok()
|
||||
self.probe(|_| {
|
||||
let ok = match coerce.coerce(source, target) {
|
||||
Ok(ok) => ok,
|
||||
_ => return false,
|
||||
};
|
||||
let mut fcx = traits::FulfillmentContext::new_in_snapshot();
|
||||
fcx.register_predicate_obligations(self, ok.obligations);
|
||||
fcx.select_where_possible(&self).is_ok()
|
||||
})
|
||||
}
|
||||
|
||||
/// Given a type and a target type, this function will calculate and return
|
||||
|
|
|
@ -341,7 +341,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
for (sp, label) in spans_and_labels {
|
||||
multi_span.push_span_label(sp, label);
|
||||
}
|
||||
err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
|
||||
err.span_note(
|
||||
multi_span,
|
||||
"closures can only be coerced to `fn` types if they do not capture any variables"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -361,15 +364,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
let pin_did = self.tcx.lang_items().pin_type();
|
||||
match expected.kind() {
|
||||
ty::Adt(def, _) if Some(def.did) != pin_did => return false,
|
||||
// This guards the `unwrap` and `mk_box` below.
|
||||
_ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false,
|
||||
_ => {}
|
||||
// This guards the `unwrap` and `mk_box` below.
|
||||
if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() {
|
||||
return false;
|
||||
}
|
||||
let boxed_found = self.tcx.mk_box(found);
|
||||
let new_found = self.tcx.mk_lang_item(boxed_found, LangItem::Pin).unwrap();
|
||||
if self.can_coerce(new_found, expected) {
|
||||
match expected.kind() {
|
||||
ty::Adt(def, _) if Some(def.did) == pin_did => (),
|
||||
_ => return false,
|
||||
}
|
||||
let box_found = self.tcx.mk_box(found);
|
||||
let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap();
|
||||
let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap();
|
||||
if self.can_coerce(pin_box_found, expected) {
|
||||
debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected);
|
||||
match found.kind() {
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
err.help("use `Box::pin`");
|
||||
|
@ -381,11 +388,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
|
||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else if self.can_coerce(pin_found, expected) {
|
||||
match found.kind() {
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
err.help("use `Box::pin`");
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue